Guide to the Secure Configuration of SUSE Linux Enterprise 15

with profile CIS SUSE Linux Enterprise 15 Benchmark
This profile defines a baseline that aligns to the Center for Internet Security® SUSE Linux Enterprise 15 Benchmark™, v1.0.0, released 06-30-2020. This profile includes Center for Internet Security® SUSE Linux Enterprise 15 CIS Benchmarks™ content.
This guide presents a catalog of security-relevant configuration settings for SUSE Linux Enterprise 15. 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 TitleCIS SUSE Linux Enterprise 15 Benchmark
Profile IDxccdf_org.ssgproject.content_profile_cis

CPE Platforms

  • cpe:/o:suse:linux_enterprise_server:15
  • cpe:/o:suse:linux_enterprise_desktop:15

Revision History

Current version: 0.1.57

  • draft (as of 2021-07-29)

Table of Contents

  1. System Settings
    1. Installing and Maintaining Software
    2. Account and Access Control
    3. System Accounting with auditd
    4. GRUB2 bootloader configuration
    5. Configure Syslog
    6. Network Configuration and Firewalls
    7. File Permissions and Masks
  2. Services
    1. Avahi Server
    2. Cron and At Daemons
    3. Deprecated services
    4. DHCP
    5. DNS Server
    6. FTP Server
    7. Web Server
    8. IMAP and POP3 Server
    9. LDAP
    10. Mail Server Software
    11. NFS and RPC
    12. Network Time Protocol
    13. Obsolete Services
    14. Print Support
    15. Proxy Server
    16. Samba(SMB) Microsoft Windows File Sharing Server
    17. SNMP Server
    18. SSH Server
    19. X Window System

Checklist

Group   Guide to the Secure Configuration of SUSE Linux Enterprise 15   Group contains 101 groups and 221 rules
Group   System Settings   Group contains 58 groups and 152 rules
[ref]   Contains rules that check correct system settings.
Group   Installing and Maintaining Software   Group contains 7 groups and 14 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   System and Software Integrity   Group contains 3 groups and 4 rules
[ref]   System and software integrity can be gained by installing antivirus, increasing system encryption strength with FIPS, verifying installed software, enabling SELinux, installing an Intrusion Prevention System, etc. However, installing or enabling integrity checking tools cannot prevent intrusions, but they can detect that an intrusion may have occurred. Requirements for integrity checking may be highly dependent on the environment in which the system will be used. Snapshot-based approaches such as AIDE may induce considerable overhead in the presence of frequent software updates.
Group   Software Integrity Checking   Group contains 2 groups and 4 rules
[ref]   Both the AIDE (Advanced Intrusion Detection Environment) software and the RPM package management system provide mechanisms for verifying the integrity of installed software. AIDE uses snapshots of file metadata (such as hashes) and compares these to current system files in order to detect changes.

The RPM package management system can conduct integrity checks by comparing information in its metadata database with files installed on the system.
Group   Verify Integrity with RPM   Group contains 2 rules
[ref]   The RPM package management system includes the ability to verify the integrity of installed packages by comparing the installed files with information about the files taken from the package metadata stored in the RPM database. Although an attacker could corrupt the RPM database (analogous to attacking the AIDE database as described above), this check can still reveal modification of important files. To list which files on the system differ from what is expected by the RPM database:
$ rpm -qVa
See the man page for rpm to see a complete explanation of each column.

Rule   Verify and Correct Ownership with RPM   [ref]

The RPM package management system can check file ownership permissions of installed software packages, including many that are important to system security. After locating a file with incorrect permissions, which can be found with
rpm -Va | awk '{ if (substr($0,6,1)=="U" || substr($0,7,1)=="G") print $NF }'
run the following command to determine which package owns it:
$ rpm -qf FILENAME
Next, run the following command to reset its permissions to the correct values:
$ sudo rpm --setugids PACKAGENAME
Warning:  Profiles may require that specific files be owned by root while the default owner defined by the vendor is different. Such files will be reported as a finding and need to be evaluated according to your policy and deployment environment.
Rationale:
Ownership of binaries and configuration files that is incorrect could allow an unauthorized user to gain privileges that they should not have. The ownership set by the vendor should be maintained. Any deviations from this baseline should be investigated.
Severity: 
high
Rule ID:xccdf_org.ssgproject.content_rule_rpm_verify_ownership
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 18, 3, 5, 6, 9, 5.10.4.1, APO01.06, APO11.04, BAI03.05, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.04, DSS05.07, DSS06.02, MEA02.01, 3.3.8, 3.4.1, CCI-001494, CCI-001496, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.7.3, 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 5.2, SR 7.6, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.12.1.2, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.5.1, A.12.6.2, A.12.7.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.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.3, A.9.4.1, A.9.4.4, A.9.4.5, CIP-003-3 R4.2, CIP-003-3 R6, CIP-007-3 R4, CIP-007-3 R4.1, CIP-007-3 R4.2, CM-6(d), CM-6(c), SI-7, SI-7(1), SI-7(6), AU-9(3), PR.AC-4, PR.DS-5, PR.IP-1, PR.PT-1, Req-11.5, SRG-OS-000256-GPOS-00097, SRG-OS-000257-GPOS-00098, SRG-OS-000278-GPOS-00108, 6.1.1

Rule   Verify and Correct File Permissions with RPM   [ref]

The RPM package management system can check file access permissions of installed software packages, including many that are important to system security. Verify that the file permissions of system files and commands match vendor values. Check the file permissions with the following command:
$ sudo rpm -Va | awk '{ if (substr($0,2,1)=="M") print $NF }'
Output indicates files that do not match vendor defaults. After locating a file with incorrect permissions, run the following command to determine which package owns it:
$ rpm -qf FILENAME

Next, run the following command to reset its permissions to the correct values:
$ sudo rpm --setperms PACKAGENAME
Warning:  Profiles may require that specific files have stricter file permissions than defined by the vendor. Such files will be reported as a finding and need to be evaluated according to your policy and deployment environment.
Rationale:
Permissions on system binaries and configuration files that are too generous could allow an unauthorized user to gain privileges that they should not have. The permissions set by the vendor should be maintained. Any deviations from this baseline should be investigated.
Severity: 
high
Rule ID:xccdf_org.ssgproject.content_rule_rpm_verify_permissions
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 18, 3, 5, 6, 9, 5.10.4.1, APO01.06, APO11.04, BAI03.05, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.04, DSS05.07, DSS06.02, MEA02.01, 3.3.8, 3.4.1, CCI-001493, CCI-001494, CCI-001495, CCI-001496, 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i), 4.3.3.3.9, 4.3.3.5.8, 4.3.3.7.3, 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 5.2, SR 7.6, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.12.1.2, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.5.1, A.12.6.2, A.12.7.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.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.3, A.9.4.1, A.9.4.4, A.9.4.5, CIP-003-3 R4.2, CIP-003-3 R6, CIP-007-3 R4, CIP-007-3 R4.1, CIP-007-3 R4.2, CM-6(d), CM-6(c), SI-7, SI-7(1), SI-7(6), AU-9(3), CM-6(a), PR.AC-4, PR.DS-5, PR.IP-1, PR.PT-1, Req-11.5, SRG-OS-000256-GPOS-00097, SRG-OS-000257-GPOS-00098, SRG-OS-000258-GPOS-00099, SRG-OS-000278-GPOS-00108, 6.1.1

Group   Verify Integrity with AIDE   Group contains 2 rules
[ref]   AIDE conducts integrity checks by comparing information about files with previously-gathered information. Ideally, the AIDE database is created immediately after initial system configuration, and then again after any software update. AIDE is highly configurable, with further configuration information located in /usr/share/doc/aide-VERSION.

Rule   Install AIDE   [ref]

The aide package can be installed with the following command:
$ sudo zypper install aide
Rationale:
The AIDE package must be installed if it is to be available for integrity checking.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_package_aide_installed
Identifiers and References

Identifiers:  CCE-83289-9

References:  BP28(R51), 1, 11, 12, 13, 14, 15, 16, 2, 3, 5, 7, 8, 9, 5.10.1.3, APO01.06, BAI01.06, BAI02.01, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.03, DSS03.05, DSS04.07, DSS05.02, DSS05.03, DSS05.05, DSS05.07, DSS06.02, DSS06.06, CCI-002699, CCI-001744, 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4, SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 4.1, SR 6.2, SR 7.6, 1034, 1288, 1341, 1417, A.11.2.4, A.12.1.2, A.12.2.1, A.12.4.1, A.12.5.1, A.12.6.2, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.14.2.7, A.15.2.1, A.8.2.3, CM-6(a), DE.CM-1, DE.CM-7, PR.DS-1, PR.DS-6, PR.DS-8, PR.IP-1, PR.IP-3, Req-11.5, SRG-OS-000363-GPOS-00150, SLES-15-010420, SV-234851r622137_rule, 1.4.1


Complexity:low
Disruption:low
Strategy:enable
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; then

zypper install -y "aide"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Strategy:enable
- name: Ensure aide is installed
  package:
    name: aide
    state: present
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CCE-83289-9
    - CJIS-5.10.1.3
    - DISA-STIG-SLES-15-010420
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-11.5
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_aide_installed

Complexity:low
Disruption:low
Strategy:enable
include install_aide

class install_aide {
  package { 'aide':
    ensure => 'installed',
  }
}


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

Rule   Configure Periodic Execution of AIDE   [ref]

At a minimum, AIDE should be configured to run a weekly scan. To implement a daily execution of AIDE at 4:05am using cron, add the following line to /etc/crontab:
05 4 * * * root /usr/sbin/aide --check
To implement a weekly execution of AIDE at 4:05am using cron, add the following line to /etc/crontab:
05 4 * * 0 root /usr/sbin/aide --check
AIDE can be executed periodically through other means; this is merely one example. The usage of cron's special time codes, such as @daily and @weekly is acceptable.
Rationale:
By default, AIDE does not install itself for periodic execution. Periodically running AIDE is necessary to reveal unexpected changes in installed files.

Unauthorized changes to the baseline configuration could make the system vulnerable to various attacks or allow unauthorized access to the operating system. Changes to operating system configurations can have unintended side effects, some of which may be relevant to security.

Detecting such changes and providing an automated response can help avoid unintended, negative consequences that could ultimately affect the security state of the operating system. The operating system's Information Management Officer (IMO)/Information System Security Officer (ISSO) and System Administrators (SAs) must be notified via email and/or monitoring system trap when there is an unauthorized modification of a configuration item.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_aide_periodic_cron_checking
Identifiers and References

Identifiers:  CCE-85671-6

References:  BP28(R51), 1, 11, 12, 13, 14, 15, 16, 2, 3, 5, 7, 8, 9, 5.10.1.3, APO01.06, BAI01.06, BAI02.01, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.03, DSS03.05, DSS04.07, DSS05.02, DSS05.03, DSS05.05, DSS05.07, DSS06.02, DSS06.06, CCI-001744, CCI-002699, CCI-002702, 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4, SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 4.1, SR 6.2, SR 7.6, A.11.2.4, A.12.1.2, A.12.2.1, A.12.4.1, A.12.5.1, A.12.6.2, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.14.2.7, A.15.2.1, A.8.2.3, SI-6(d), DE.CM-1, DE.CM-7, PR.DS-1, PR.DS-6, PR.DS-8, PR.IP-1, PR.IP-3, Req-11.5, SRG-OS-000363-GPOS-00150, SRG-OS-000446-GPOS-00200, SRG-OS-000447-GPOS-00201, SLES-15-010570, SV-234864r622137_rule


Complexity:low
Disruption:low
Strategy:restrict
- name: Ensure AIDE is installed
  package:
    name: '{{ item }}'
    state: present
  with_items:
    - aide
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CCE-85671-6
    - CJIS-5.10.1.3
    - DISA-STIG-SLES-15-010570
    - NIST-800-53-SI-6(d)
    - PCI-DSS-Req-11.5
    - aide_periodic_cron_checking
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Configure Periodic Execution of AIDE
  cron:
    name: run AIDE check
    minute: 5
    hour: 4
    weekday: 0
    user: root
    job: /usr/sbin/aide --check
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CCE-85671-6
    - CJIS-5.10.1.3
    - DISA-STIG-SLES-15-010570
    - NIST-800-53-SI-6(d)
    - PCI-DSS-Req-11.5
    - aide_periodic_cron_checking
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
Group   Disk Partitioning   Group contains 6 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. See the LVM HOWTO at http://tldp.org/HOWTO/LVM-HOWTO/ for more detailed information on LVM.

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
Identifiers and References

Identifiers:  CCE-85639-3

References:  BP28(R12), 12, 15, 8, APO13.01, DSS05.02, CCI-000366, CCI-001208, 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, A.13.1.1, A.13.2.1, A.14.1.3, CM-6(a), SC-5(2), PR.PT-4, SRG-OS-000480-GPOS-00227, SLES-15-040200, SV-235004r622137_rule, 1.1.14

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
Identifiers and References

References:  BP28(R12), 12, 15, 8, APO13.01, DSS05.02, CCI-000366, 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, A.13.1.1, A.13.2.1, A.14.1.3, CM-6(a), SC-5(2), PR.PT-4, SRG-OS-000480-GPOS-00227, 1.1.2

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
Identifiers and References

Identifiers:  CCE-85640-1

References:  BP28(R12), 12, 15, 8, APO13.01, DSS05.02, CCI-000366, 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, A.13.1.1, A.13.2.1, A.14.1.3, CM-6(a), SC-5(2), PR.PT-4, SRG-OS-000480-GPOS-00227, SRG-OS-000341-VMM-001220, SLES-15-040210, SV-235005r622137_rule, 1.1.7

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

System logs are stored in the /var/log directory. Ensure that it 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: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_partition_for_var_log
Identifiers and References

References:  BP28(R12), BP28(R47), 1, 12, 14, 15, 16, 3, 5, 6, 8, APO11.04, APO13.01, BAI03.05, DSS05.02, DSS05.04, DSS05.07, MEA02.01, CCI-000366, 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, SR 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, 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, CIP-007-3 R6.5, CM-6(a), AU-4, SC-5(2), PR.PT-1, PR.PT-4, SRG-OS-000480-GPOS-00227

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

Audit logs are stored in the /var/log/audit directory. Ensure that it has its own partition or logical volume at installation time, or migrate it later 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
Identifiers and References

Identifiers:  CCE-85618-7

References:  BP28(R43), 1, 12, 13, 14, 15, 16, 2, 3, 5, 6, 8, APO11.04, APO13.01, BAI03.05, BAI04.04, DSS05.02, DSS05.04, DSS05.07, MEA02.01, CCI-000366, CCI-001849, 164.312(a)(2)(ii), 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, SR 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, A.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, CIP-007-3 R6.5, CM-6(a), AU-4, SC-5(2), PR.DS-4, PR.PT-1, PR.PT-4, SRG-OS-000341-GPOS-00132, SRG-OS-000480-GPOS-00227, SRG-OS-000341-VMM-001220, SLES-15-030810, SV-234980r622137_rule, 1.1.13

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

The /var/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 /var/tmp partition is used as temporary storage by many programs. Placing /var/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_var_tmp
Identifiers and References

References:  BP28(R12), SRG-OS-000480-GPOS-00227, 1.1.8

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   Install sudo Package   [ref]

The sudo package can be installed with the following command:
$ sudo zypper install sudo
Rationale:
sudo is a program designed to allow a system administrator to give limited root privileges to users and log root activity. The basic philosophy is to give as few privileges as possible but still allow system users to get their work done.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_package_sudo_installed
Identifiers and References

References:  BP28(R19), 1382, 1384, 1386, CM-6(a), SRG-OS-000324-GPOS-00125


Complexity:low
Disruption:low
Strategy:enable
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; then

zypper install -y "sudo"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Strategy:enable
- name: Ensure sudo is installed
  package:
    name: sudo
    state: present
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - NIST-800-53-CM-6(a)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_sudo_installed

Complexity:low
Disruption:low
Strategy:enable
include install_sudo

class install_sudo {
  package { 'sudo':
    ensure => 'installed',
  }
}


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

Rule   Ensure Only Users Logged In To Real tty Can Execute Sudo - sudo use_pty   [ref]

The sudo use_pty tag, when specified, will only execute sudo commands from users logged in to a real tty. This should be enabled by making sure that the use_pty tag exists in /etc/sudoers configuration file or any sudo configuration snippets in /etc/sudoers.d/.
Rationale:
Requiring that sudo commands be run in a pseudo-terminal can prevent an attacker from retaining access to the user's terminal after the main program has finished executing.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_sudo_add_use_pty
Identifiers and References

References:  BP28(R58)


Complexity:low
Disruption:low
Strategy:restrict

if /usr/sbin/visudo -qcf /etc/sudoers; then
    cp /etc/sudoers /etc/sudoers.bak
    if ! grep -P '^[\s]*Defaults.*\buse_pty\b.*$' /etc/sudoers; then
        # sudoers file doesn't define Option use_pty
        echo "Defaults use_pty" >> /etc/sudoers
    fi
    
    # Check validity of sudoers and cleanup bak
    if /usr/sbin/visudo -qcf /etc/sudoers; then
        rm -f /etc/sudoers.bak
    else
        echo "Fail to validate remediated /etc/sudoers, reverting to original file."
        mv /etc/sudoers.bak /etc/sudoers
        false
    fi
else
    echo "Skipping remediation, /etc/sudoers failed to validate"
    false
fi

Complexity:low
Disruption:low
Strategy:restrict
- name: Ensure use_pty is enabled in /etc/sudoers
  lineinfile:
    path: /etc/sudoers
    regexp: ^[\s]*Defaults.*\buse_pty\b.*$
    line: Defaults use_pty
    validate: /usr/sbin/visudo -cf %s
  tags:
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_add_use_pty
Group   Updating Software   Group contains 2 rules
[ref]   The zypper command line tool is used to install and update software packages. The system also provides a graphical software update tool in the System menu, in the Administration submenu, called Software Update.

SUSE Linux Enterprise 15 systems contain an installed software catalog called the RPM database, which records metadata of installed packages. Consistently using zypper or the graphical Software Update for all software installation allows for insight into the current inventory of installed software on the system.

Rule   Ensure gpgcheck Enabled In Main zypper Configuration   [ref]

The gpgcheck option controls whether RPM packages' signatures are always checked prior to installation. To configure zypper to check package signatures before installing them, ensure the following line appears in /etc/zypp/zypp.conf in the [main] section:
gpgcheck=1
Rationale:
Changes to any software components can have significant effects on the overall security of the operating system. This requirement ensures the software has not been tampered with and that it has been provided by a trusted vendor.
Accordingly, patches, service packs, device drivers, or operating system components must be signed with a certificate recognized and approved by the organization.
Verifying the authenticity of the software prior to installation validates the integrity of the patch or upgrade received from a vendor. This ensures the software has not been tampered with and that it has been provided by a trusted vendor. Self-signed certificates are disallowed by this requirement. Certificates used to verify the software must be from an approved Certificate Authority (CA).
Severity: 
high
Rule ID:xccdf_org.ssgproject.content_rule_ensure_gpgcheck_globally_activated
Identifiers and References

Identifiers:  CCE-83290-7

References:  BP28(R15), 11, 2, 3, 9, 5.10.4.1, APO01.06, BAI03.05, BAI06.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS06.02, 3.4.8, CCI-001749, 164.308(a)(1)(ii)(D), 164.312(b), 164.312(c)(1), 164.312(c)(2), 164.312(e)(2)(i), 4.3.4.3.2, 4.3.4.3.3, 4.3.4.4.4, SR 3.1, SR 3.3, SR 3.4, SR 3.8, SR 7.6, A.11.2.4, A.12.1.2, A.12.2.1, A.12.5.1, A.12.6.2, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, CM-5(3), SI-7, SC-12, SC-12(3), CM-6(a), SA-12, SA-12(10), CM-11(a), CM-11(b), PR.DS-6, PR.DS-8, PR.IP-1, FPT_TUD_EXT.1, FPT_TUD_EXT.2, Req-6.2, SRG-OS-000366-GPOS-00153, SRG-OS-000366-VMM-001430, SRG-OS-000370-VMM-001460, SRG-OS-000404-VMM-001650, SLES-15-010430, SV-234852r622137_rule


Complexity:low
Disruption:medium
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
    - CCE-83290-7
    - CJIS-5.10.4.1
    - DISA-STIG-SLES-15-010430
    - NIST-800-171-3.4.8
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-53-CM-5(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SA-12
    - NIST-800-53-SA-12(10)
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SI-7
    - PCI-DSS-Req-6.2
    - ensure_gpgcheck_globally_activated
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

- name: Ensure GPG check is globally activated (zypper)
  ini_file:
    dest: /etc/zypp/zypp.conf
    section: main
    option: gpgcheck
    value: 1
    no_extra_spaces: true
    create: false
  when: '"zypper" in ansible_facts.packages'
  tags:
    - CCE-83290-7
    - CJIS-5.10.4.1
    - DISA-STIG-SLES-15-010430
    - NIST-800-171-3.4.8
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-53-CM-5(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SA-12
    - NIST-800-53-SA-12(10)
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SI-7
    - PCI-DSS-Req-6.2
    - ensure_gpgcheck_globally_activated
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

Rule   Ensure Software Patches Installed   [ref]

If the system is configured for online updates, invoking the following command will list available security updates:
$ sudo zypper refresh && sudo zypper list-patches -g security


NOTE: U.S. Defense systems are required to be patched within 30 days or sooner as local policy dictates.
Rationale:
Installing software updates is a fundamental mitigation against the exploitation of publicly-known vulnerabilities. If the most recent security patches and updates are not installed, unauthorized users may take advantage of weaknesses in the unpatched software. The lack of prompt attention to patching could result in a system compromise.
Severity: 
high
Rule ID:xccdf_org.ssgproject.content_rule_security_patches_up_to_date
Identifiers and References

Identifiers:  CCE-83261-8

References:  BP28(R08), 18, 20, 4, 5.10.4.1, APO12.01, APO12.02, APO12.03, APO12.04, BAI03.10, DSS05.01, DSS05.02, CCI-000366, CCI-001227, 4.2.3, 4.2.3.12, 4.2.3.7, 4.2.3.9, A.12.6.1, A.14.2.3, A.16.1.3, A.18.2.2, A.18.2.3, SI-2(5), SI-2(c), CM-6(a), ID.RA-1, PR.IP-12, FMT_MOF_EXT.1, Req-6.2, SRG-OS-000480-GPOS-00227, SRG-OS-000480-VMM-002000, SLES-15-010010, SV-234802r622137_rule


Complexity:low
Disruption:high
Reboot:true
Strategy:patch
- name: Security patches are up to date
  package:
    name: '*'
    state: latest
  tags:
    - CCE-83261-8
    - CJIS-5.10.4.1
    - DISA-STIG-SLES-15-010010
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-2(5)
    - NIST-800-53-SI-2(c)
    - PCI-DSS-Req-6.2
    - high_disruption
    - high_severity
    - low_complexity
    - patch_strategy
    - reboot_required
    - security_patches_up_to_date
    - skip_ansible_lint
Group   Account and Access Control   Group contains 14 groups and 31 rules
[ref]   In traditional Unix security, if an attacker gains shell access to a certain login account, they can perform any action or access any file to which that account has access. Therefore, making it more difficult for unauthorized people to gain shell access to accounts, particularly to privileged accounts, is a necessary part of securing a system. This section introduces mechanisms for restricting access to accounts under SUSE Linux Enterprise 15.
Group   Warning Banners for System Accesses   Group contains 1 group and 6 rules
[ref]   Each system should expose as little information about itself as possible.

System banners, which are typically displayed just before a login prompt, give out information about the service or the host's operating system. This might include the distribution name and the system kernel version, and the particular version of a network service. This information can assist intruders in gaining access to the system as it can reveal whether the system is running vulnerable software. Most network services can be configured to limit what information is displayed.

Many organizations implement security policies that require a system banner provide notice of the system's ownership, provide warning to unauthorized users, and remind authorized users of their consent to monitoring.
Group   Implement a GUI Warning Banner   Group contains 2 rules

Rule   Enable GNOME3 Login Warning Banner   [ref]

In the default graphical environment, displaying a login warning banner in the GNOME Display Manager's login screen can be enabled on the login screen by setting banner-message-enable to true.

To enable, add or edit banner-message-enable to /etc/dconf/db/gdm.d/00-security-settings. For example:
[org/gnome/login-screen]
banner-message-enable=true
Once the setting has been added, add a lock to /etc/dconf/db/gdm.d/locks/00-security-settings-lock to prevent user modification. For example:
/org/gnome/login-screen/banner-message-enable
After the settings have been set, run dconf update. The banner text must also be set.
Rationale:
Display of a standardized and approved use notification before granting access to the operating system ensures privacy and security notification verbiage used is consistent with applicable federal laws, Executive Orders, directives, policies, regulations, standards, and guidance.

For U.S. Government systems, system use notifications are required only for access via login interfaces with human users and are not required when such human interfaces do not exist.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_dconf_gnome_banner_enabled
Identifiers and References

Identifiers:  CCE-83265-9

References:  1, 12, 15, 16, DSS05.04, DSS05.10, DSS06.10, 3.1.9, CCI-000048, CCI-000050, CCI-001384, CCI-001385, CCI-001386, CCI-001387, CCI-001388, 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, SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9, A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3, AC-8(a), AC-8(b), AC-8(c), PR.AC-7, FMT_MOF_EXT.1, SRG-OS-000023-GPOS-00006, SRG-OS-000024-GPOS-00007, SRG-OS-000228-GPOS-00088, SLES-15-010080, SV-234808r622137_rule


# Remediation is applicable only in certain platforms
if rpm --quiet -q gdm; then

# Check for setting in any of the DConf db directories
# If files contain ibus or distro, ignore them.
# The assignment assumes that individual filenames don't contain :
readarray -t SETTINGSFILES < <(grep -r "\\[org/gnome/login-screen\\]" "/etc/dconf/db/" | grep -v 'distro\|ibus' | cut -d":" -f1)
DCONFFILE="/etc/dconf/db/gdm.d/00-security-settings"
DBDIR="/etc/dconf/db/gdm.d"

mkdir -p "${DBDIR}"

if [ "${#SETTINGSFILES[@]}" -eq 0 ]
then
    [ ! -z ${DCONFFILE} ] || echo "" >> ${DCONFFILE}
    printf '%s\n' "[org/gnome/login-screen]" >> ${DCONFFILE}
    printf '%s=%s\n' "banner-message-enable" "true" >> ${DCONFFILE}
else
    escaped_value="$(sed -e 's/\\/\\\\/g' <<< "true")"
    if grep -q "^\\s*banner-message-enable\\s*=" "${SETTINGSFILES[@]}"
    then
        
        sed -i "s/\\s*banner-message-enable\\s*=\\s*.*/banner-message-enable=${escaped_value}/g" "${SETTINGSFILES[@]}"
    else
        sed -i "\\|\\[org/gnome/login-screen\\]|a\\banner-message-enable=${escaped_value}" "${SETTINGSFILES[@]}"
    fi
fi

dconf update
# Check for setting in any of the DConf db directories
LOCKFILES=$(grep -r "^/org/gnome/login-screen/banner-message-enable$" "/etc/dconf/db/" | grep -v 'distro\|ibus' | cut -d":" -f1)
LOCKSFOLDER="/etc/dconf/db/gdm.d/locks"

mkdir -p "${LOCKSFOLDER}"

if [[ -z "${LOCKFILES}" ]]
then
    echo "/org/gnome/login-screen/banner-message-enable" >> "/etc/dconf/db/gdm.d/locks/00-security-settings-lock"
fi

dconf update

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:medium
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
    - CCE-83265-9
    - DISA-STIG-SLES-15-010080
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(b)
    - NIST-800-53-AC-8(c)
    - dconf_gnome_banner_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

- name: Enable GNOME3 Login Warning Banner
  ini_file:
    dest: /etc/dconf/db/gdm.d/00-security-settings
    section: org/gnome/login-screen
    option: banner-message-enable
    value: 'true'
    create: true
    no_extra_spaces: true
  when: '"gdm" in ansible_facts.packages'
  tags:
    - CCE-83265-9
    - DISA-STIG-SLES-15-010080
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(b)
    - NIST-800-53-AC-8(c)
    - dconf_gnome_banner_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

- name: Prevent user modification of GNOME banner-message-enabled
  lineinfile:
    path: /etc/dconf/db/gdm.d/locks/00-security-settings-lock
    regexp: ^/org/gnome/login-screen/banner-message-enable$
    line: /org/gnome/login-screen/banner-message-enable
    create: true
  when: '"gdm" in ansible_facts.packages'
  tags:
    - CCE-83265-9
    - DISA-STIG-SLES-15-010080
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(b)
    - NIST-800-53-AC-8(c)
    - dconf_gnome_banner_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

- name: Dconf Update
  command: dconf update
  when: '"gdm" in ansible_facts.packages'
  tags:
    - CCE-83265-9
    - DISA-STIG-SLES-15-010080
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(b)
    - NIST-800-53-AC-8(c)
    - dconf_gnome_banner_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

Rule   Modify the System Login Banner   [ref]

To configure the system login banner edit /etc/issue. Replace the default text with a message compliant with the local site policy or a legal disclaimer. The DoD required text is either:

You are accessing a U.S. Government (USG) Information System (IS) that is provided for USG-authorized use only. By using this IS (which includes any device attached to this IS), you consent to the following conditions:
-The USG routinely intercepts and monitors communications on this IS for purposes including, but not limited to, penetration testing, COMSEC monitoring, network operations and defense, personnel misconduct (PM), law enforcement (LE), and counterintelligence (CI) investigations.
-At any time, the USG may inspect and seize data stored on this IS.
-Communications using, or data stored on, this IS are not private, are subject to routine monitoring, interception, and search, and may be disclosed or used for any USG-authorized purpose.
-This IS includes security measures (e.g., authentication and access controls) to protect USG interests -- not for your personal benefit or privacy.
-Notwithstanding the above, using this IS does not constitute consent to PM, LE or CI investigative searching or monitoring of the content of privileged communications, or work product, related to personal representation or services by attorneys, psychotherapists, or clergy, and their assistants. Such communications and work product are private and confidential. See User Agreement for details.


OR:

I've read & consent to terms in IS user agreem't.
Rationale:
Display of a standardized and approved use notification before granting access to the operating system ensures privacy and security notification verbiage used is consistent with applicable federal laws, Executive Orders, directives, policies, regulations, standards, and guidance.

System use notifications are required only for access via login interfaces with human users and are not required when such human interfaces do not exist.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_banner_etc_issue
Identifiers and References

Identifiers:  CCE-83262-6

References:  1, 12, 15, 16, DSS05.04, DSS05.10, DSS06.10, 3.1.9, CCI-000048, CCI-000050, 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, SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9, A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3, AC-8(a), AC-8(c), PR.AC-7, FMT_MOF_EXT.1, SRG-OS-000023-GPOS-00006, SRG-OS-000024-GPOS-00007, SRG-OS-000023-VMM-000060, SRG-OS-000024-VMM-000070, SLES-15-010020, SV-234803r622137_rule


Complexity:low
Disruption:medium
- name: XCCDF Value login_banner_text # promote to variable
  set_fact:
    login_banner_text: !!str (N/A)
  tags:
    - always

- name: Modify the System Login Banner - remove incorrect banner
  file:
    state: absent
    path: /etc/issue
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CCE-83262-6
    - DISA-STIG-SLES-15-010020
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - banner_etc_issue
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

- name: Modify the System Login Banner - add correct banner
  lineinfile:
    dest: /etc/issue
    line: '{{ login_banner_text | regex_replace("^\^(.*)\$$", "\1") | regex_replace("^\((.*)\|.*\)$",
      "\1") | regex_replace("\[\\s\\n\]\+"," ") | regex_replace("\(\?:\[\\n\]\+\|\(\?:\\\\n\)\+\)",
      "\n") | regex_replace("\\", "") | wordwrap() }}'
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CCE-83262-6
    - DISA-STIG-SLES-15-010020
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - banner_etc_issue
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

Rule   Modify the System Message of the Day Banner   [ref]

To configure the system message banner edit /etc/motd. Replace the default text with a message compliant with the local site policy or a legal disclaimer. The DoD required text is either:

You are accessing a U.S. Government (USG) Information System (IS) that is provided for USG-authorized use only. By using this IS (which includes any device attached to this IS), you consent to the following conditions:
-The USG routinely intercepts and monitors communications on this IS for purposes including, but not limited to, penetration testing, COMSEC monitoring, network operations and defense, personnel misconduct (PM), law enforcement (LE), and counterintelligence (CI) investigations.
-At any time, the USG may inspect and seize data stored on this IS.
-Communications using, or data stored on, this IS are not private, are subject to routine monitoring, interception, and search, and may be disclosed or used for any USG-authorized purpose.
-This IS includes security measures (e.g., authentication and access controls) to protect USG interests -- not for your personal benefit or privacy.
-Notwithstanding the above, using this IS does not constitute consent to PM, LE or CI investigative searching or monitoring of the content of privileged communications, or work product, related to personal representation or services by attorneys, psychotherapists, or clergy, and their assistants. Such communications and work product are private and confidential. See User Agreement for details.


OR:

I've read & consent to terms in IS user agreem't.
Rationale:
Display of a standardized and approved use notification before granting access to the operating system ensures privacy and security notification verbiage used is consistent with applicable federal laws, Executive Orders, directives, policies, regulations, standards, and guidance.

System use notifications are required only for access via login interfaces with human users and are not required when such human interfaces do not exist.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_banner_etc_motd
Identifiers and References

Rule   Verify permissions on System Login Banner   [ref]

To properly set the permissions of /etc/issue, run the command:
$ sudo chmod 0644 /etc/issue
Rationale:
Display of a standardized and approved use notification before granting access to the operating system ensures privacy and security notification verbiage used is consistent with applicable federal laws, Executive Orders, directives, policies, regulations, standards, and guidance.
Proper permissions will ensure that only root user can modify the banner.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_etc_issue
Identifiers and References

Complexity:low
Disruption:low
Strategy:configure


chmod 0644 /etc/issue

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/issue
  stat:
    path: /etc/issue
  register: file_exists
  tags:
    - configure_strategy
    - file_permissions_etc_issue
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

- name: Ensure permission 0644 on /etc/issue
  file:
    path: /etc/issue
    mode: '0644'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
    - configure_strategy
    - file_permissions_etc_issue
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

Rule   Verify permissions on Message of the Day Banner   [ref]

To properly set the permissions of /etc/motd, run the command:
$ sudo chmod 0644 /etc/motd
Rationale:
Display of a standardized and approved use notification before granting access to the operating system ensures privacy and security notification verbiage used is consistent with applicable federal laws, Executive Orders, directives, policies, regulations, standards, and guidance.
Proper permissions will ensure that only root user can modify the banner.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_etc_motd
Identifiers and References

Complexity:low
Disruption:low
Strategy:configure


chmod 0644 /etc/motd

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/motd
  stat:
    path: /etc/motd
  register: file_exists
  tags:
    - configure_strategy
    - file_permissions_etc_motd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

- name: Ensure permission 0644 on /etc/motd
  file:
    path: /etc/motd
    mode: '0644'
  when: file_exists.stat is defined and file_exists.stat.exists
  tags:
    - configure_strategy
    - file_permissions_etc_motd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
Group   Protect Accounts by Configuring PAM   Group contains 4 groups and 9 rules
[ref]   PAM, or Pluggable Authentication Modules, is a system which implements modular authentication for Linux programs. PAM provides a flexible and configurable architecture for authentication, and it should be configured to minimize exposure to unnecessary risk. This section contains guidance on how to accomplish that.

PAM is implemented as a set of shared objects which are loaded and invoked whenever an application wishes to authenticate a user. Typically, the application must be running as root in order to take advantage of PAM, because PAM's modules often need to be able to access sensitive stores of account information, such as /etc/shadow. Traditional privileged network listeners (e.g. sshd) or SUID programs (e.g. sudo) already meet this requirement. An SUID root application, userhelper, is provided so that programs which are not SUID or privileged themselves can still take advantage of PAM.

PAM looks in the directory /etc/pam.d for application-specific configuration information. For instance, if the program login attempts to authenticate a user, then PAM's libraries follow the instructions in the file /etc/pam.d/login to determine what actions should be taken.

One very important file in /etc/pam.d is /etc/pam.d/system-auth. This file, which is included by many other PAM configuration files, defines 'default' system authentication measures. Modifying this file is a good way to make far-reaching authentication changes, for instance when implementing a centralized authentication service.
Warning:  Be careful when making changes to PAM's configuration files. The syntax for these files is complex, and modifications can have unexpected consequences. The default configurations shipped with applications should be sufficient for most users.
Warning:  Running authconfig or system-config-authentication will re-write the PAM configuration files, destroying any manually made changes and replacing them with a series of system defaults. One reference to the configuration file syntax can be found at http://www.linux-pam.org/Linux-PAM-html/sag-configuration-file.html.
Group   Set Lockouts for Failed Password Attempts   Group contains 2 rules
[ref]   The pam_faillock PAM module provides the capability to lock out user accounts after a number of failed login attempts. Its documentation is available in /usr/share/doc/pam-VERSION/txts/README.pam_faillock.

Warning:  Locking out user accounts presents the risk of a denial-of-service attack. The lockout policy must weigh whether the risk of such a denial-of-service attack outweighs the benefits of thwarting password guessing attacks.

Rule   Limit Password Reuse   [ref]

Do not allow users to reuse recent passwords. This can be accomplished by using the remember option for the pam_pwhistory PAM modules.

In the file /etc/pam.d/common-password, make sure the parameters remember and use_authtok are present, and that the value for the remember parameter is 5 or greater. For example:
password requisite pam_pwhistory.so ...existing_options... remember=5 use_authtok
The DoD STIG requirement is 5 passwords.
Rationale:
Preventing re-use of previous passwords helps ensure that a compromised password is not re-used by a user.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_password_pam_pwhistory_remember
Identifiers and References

References:  CCI-000200, SRG-OS-000077-GPOS-00045


Complexity:low
Disruption:low
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
    - accounts_password_pam_pwhistory_remember
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
- name: XCCDF Value var_password_pam_remember # promote to variable
  set_fact:
    var_password_pam_remember: !!str 5
  tags:
    - always

- name: Set control_flag fact
  set_fact:
    control_flag: requisite
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_password_pam_pwhistory_remember
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check to see if 'pam_pwhistory.so' module is configured in '/etc/pam.d/common-password'
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+\S+\s+pam_pwhistory.so' /etc/pam.d/common-password || true
  register: check_pam_module_result
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_password_pam_pwhistory_remember
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Configure 'pam_pwhistory.so' module in '/etc/pam.d/common-password'
  lineinfile:
    path: /etc/pam.d/common-password
    line: password requisite pam_pwhistory.so
    state: present
  when:
    - '"pam" in ansible_facts.packages'
    - '"pam_pwhistory.so" not in check_pam_module_result.stdout'
  tags:
    - accounts_password_pam_pwhistory_remember
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure 'pam_pwhistory.so' module has conforming control flag
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+)\S+(\s+pam_pwhistory.so\s+.*)
    line: \g<1>requisite\g<2>
    backrefs: true
  when:
    - '"pam" in ansible_facts.packages'
    - control_flag|length
  tags:
    - accounts_password_pam_pwhistory_remember
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure "pam_pwhistory.so" module has argument "remember={{ var_password_pam_remember
    }}"
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_pwhistory.so(?:\s+\S+)*\s+remember=)(?:\S+)((\s+\S+)*\s*\\*\s*)$
    line: \g<1>{{ var_password_pam_remember }}\g<2>
    backrefs: true
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_password_pam_pwhistory_remember
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check the presence of "remember" argument in "pam_pwhistory.so" module
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+requisite\s+pam_pwhistory.so.*\s+remember(=|\s|\s*$)' /etc/pam.d/common-password || true
  register: check_pam_module_argument_result
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_password_pam_pwhistory_remember
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Add "remember" argument to "pam_pwhistory.so" module
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_pwhistory.so)((\s+\S+)*\s*(\\)*$)
    line: \g<1> remember={{ var_password_pam_remember }}\g<2>
    backrefs: true
  when:
    - '"pam" in ansible_facts.packages'
    - '"remember" not in check_pam_module_argument_result.stdout'
  tags:
    - accounts_password_pam_pwhistory_remember
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Set argument_value fact
  set_fact:
    argument_value: ''
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_password_pam_pwhistory_remember
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure "pam_pwhistory.so" module has argument "use_authtok"
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_pwhistory.so(?:\s+\S+)*\s+use_authtok=)(?!)\S*((\s+\S+)*\s*\\*\s*)$
    line: \g<1>\g<2>
    backrefs: true
  when:
    - '"pam" in ansible_facts.packages'
    - argument_value|length
  tags:
    - accounts_password_pam_pwhistory_remember
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check the presence of "use_authtok" argument in "pam_pwhistory.so" module
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+requisite\s+pam_pwhistory.so.*\s+use_authtok(=|\s|\s*$)' /etc/pam.d/common-password || true
  register: check_pam_module_argument_result
  when: '"pam" in ansible_facts.packages'
  tags:
    - accounts_password_pam_pwhistory_remember
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Add "use_authtok" argument to "pam_pwhistory.so" module
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_pwhistory.so)((\s+\S+)*\s*(\\)*$)
    line: \g<1> use_authtok\g<2>
    backrefs: true
  when:
    - '"pam" in ansible_facts.packages'
    - '"use_authtok" not in check_pam_module_argument_result.stdout'
  tags:
    - accounts_password_pam_pwhistory_remember
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Rule   Set Deny For Failed Password Attempts   [ref]

The SUSE operating system must lock an account after three consecutive invalid access attempts.
Rationale:
By limiting the number of failed logon attempts, the risk of unauthorized system access via user password guessing, otherwise known as brute-force attacks, is reduced. Limits are imposed by locking the account. To configure the operating system to lock an account after three unsuccessful consecutive access attempts using pam_tally2.so, modify the content of both /etc/pam.d/common-auth and /etc/pam.d/common-account as follows:

  • add or modify the pam_tally2.so module line in /etc/pam.d/common-auth to ensure both onerr=fail and deny=3 are present. For example:
    auth required pam_tally2.so onerr=fail silent audit deny=3
  • add or modify the following line in /etc/pam.d/common-account:
    account required pam_tally2.so
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_passwords_pam_tally2
Identifiers and References

Identifiers:  CCE-85554-4

References:  CCI-000044, SRG-OS-000021-GPOS-00005, SLES-15-020010, SV-234867r622137_rule


function ensure_pam_module_options {
	if [ $# -lt 7 ] || [ $# -gt 8 ] ; then
                echo "$0 requires seven or eight arguments" >&2
                exit 1
        fi
	local _pamFile="$1" _type="$2" _control="$3" _module="$4" _option="$5" _valueRegex="$6" _defaultValue="$7"
	local _remove_argument=""
	if [ $# -eq 8 ] ; then
        	_remove_argument="$8"
		# convert it to lowercase
		_remove_argument=${_remove_argument,,}
	fi

	# make sure that we have a line like this in ${_pamFile} (additional options are left as-is):
	# ${_type} ${_control} ${_module} ${_option}=${_valueRegex}

	if ! [ -e "$_pamFile" ] ; then
		echo "$_pamFile doesn't exist" >&2
		exit 1
	fi

	# if remove argument only
	if [ "${_remove_argument}" = "yes" -o "${_remove_argument}" = "true" ] ; then
		sed --follow-symlinks -i -E -e "s/^(\\s*${_type}\\s+\\S+\\s+${_module}(\\s.+)?)\\s${_option}(=\\S+)?/\\1/" "${_pamFile}"
		exit 0
	fi

	# non-empty values need to be preceded by an equals sign
	[ -n "${_valueRegex}" ] && _valueRegex="=${_valueRegex}"
	# add an equals sign to non-empty values
	[ -n "${_defaultValue}" ] && _defaultValue="=${_defaultValue}"

	# fix 'type' if it's wrong
	if grep -q -P "^\\s*(?"'!'"${_type}\\s)[[:alnum:]]+\\s+[[:alnum:]]+\\s+${_module}" < "${_pamFile}" ; then
		sed --follow-symlinks -i -E -e "s/^(\\s*)[[:alnum:]]+(\\s+[[:alnum:]]+\\s+${_module})/\\1${_type}\\2/" "${_pamFile}"
	fi

	# fix 'control' if it's wrong
	if grep -q -P "^\\s*${_type}\\s+(?"'!'"${_control})[[:alnum:]]+\\s+${_module}" < "${_pamFile}" ; then
		sed --follow-symlinks -i -E -e "s/^(\\s*${_type}\\s+)[[:alnum:]]+(\\s+${_module})/\\1${_control}\\2/" "${_pamFile}"
	fi

	# fix the value for 'option' if one exists but does not match '_valueRegex'
    if grep -q -P "^\\s*${_type}\\s+${_control}\\s+${_module}(\\s.+)?\\s+${_option}(?"'!'"${_valueRegex}(\\s|\$))" < "${_pamFile}" ; then
		sed --follow-symlinks -i -E -e "s/^(\\s*${_type}\\s+${_control}\\s+${_module}(\\s.+)?\\s)${_option}=[^[:space:]]*/\\1${_option}${_defaultValue}/" "${_pamFile}"

    # add 'option=default' if option is not set
	elif grep -q -E "^\\s*${_type}\\s+${_control}\\s+${_module}" < "${_pamFile}" &&
         grep    -E "^\\s*${_type}\\s+${_control}\\s+${_module}" < "${_pamFile}" | grep -q -E -v "\\s${_option}(=|\\s|\$)" ; then

		sed --follow-symlinks -i -E -e "s/^(\\s*${_type}\\s+${_control}\\s+${_module}[^\\n]*)/\\1 ${_option}${_defaultValue}/" "${_pamFile}"
	# add a new entry if none exists
	elif ! grep -q -P "^\\s*${_type}\\s+${_control}\\s+${_module}(\\s.+)?\\s+${_option}${_valueRegex}(\\s|\$)" < "${_pamFile}" ; then
		echo "${_type} ${_control} ${_module} ${_option}${_defaultValue}" >> "${_pamFile}"
	fi
}
ensure_pam_module_options '/etc/pam.d/common-auth' 'auth' 'required' 'pam_tally2.so' 'deny' '[123]' '3'
ensure_pam_module_options '/etc/pam.d/common-auth' 'auth' 'required' 'pam_tally2.so' 'onerr' '(fail)' 'fail'
function ensure_pam_module_options {
	if [ $# -lt 7 ] || [ $# -gt 8 ] ; then
                echo "$0 requires seven or eight arguments" >&2
                exit 1
        fi
	local _pamFile="$1" _type="$2" _control="$3" _module="$4" _option="$5" _valueRegex="$6" _defaultValue="$7"
	local _remove_argument=""
	if [ $# -eq 8 ] ; then
        	_remove_argument="$8"
		# convert it to lowercase
		_remove_argument=${_remove_argument,,}
	fi

	# make sure that we have a line like this in ${_pamFile} (additional options are left as-is):
	# ${_type} ${_control} ${_module} ${_option}=${_valueRegex}

	if ! [ -e "$_pamFile" ] ; then
		echo "$_pamFile doesn't exist" >&2
		exit 1
	fi

	# if remove argument only
	if [ "${_remove_argument}" = "yes" -o "${_remove_argument}" = "true" ] ; then
		sed --follow-symlinks -i -E -e "s/^(\\s*${_type}\\s+\\S+\\s+${_module}(\\s.+)?)\\s${_option}(=\\S+)?/\\1/" "${_pamFile}"
		exit 0
	fi

	# non-empty values need to be preceded by an equals sign
	[ -n "${_valueRegex}" ] && _valueRegex="=${_valueRegex}"
	# add an equals sign to non-empty values
	[ -n "${_defaultValue}" ] && _defaultValue="=${_defaultValue}"

	# fix 'type' if it's wrong
	if grep -q -P "^\\s*(?"'!'"${_type}\\s)[[:alnum:]]+\\s+[[:alnum:]]+\\s+${_module}" < "${_pamFile}" ; then
		sed --follow-symlinks -i -E -e "s/^(\\s*)[[:alnum:]]+(\\s+[[:alnum:]]+\\s+${_module})/\\1${_type}\\2/" "${_pamFile}"
	fi

	# fix 'control' if it's wrong
	if grep -q -P "^\\s*${_type}\\s+(?"'!'"${_control})[[:alnum:]]+\\s+${_module}" < "${_pamFile}" ; then
		sed --follow-symlinks -i -E -e "s/^(\\s*${_type}\\s+)[[:alnum:]]+(\\s+${_module})/\\1${_control}\\2/" "${_pamFile}"
	fi

	# fix the value for 'option' if one exists but does not match '_valueRegex'
    if grep -q -P "^\\s*${_type}\\s+${_control}\\s+${_module}(\\s.+)?\\s+${_option}(?"'!'"${_valueRegex}(\\s|\$))" < "${_pamFile}" ; then
		sed --follow-symlinks -i -E -e "s/^(\\s*${_type}\\s+${_control}\\s+${_module}(\\s.+)?\\s)${_option}=[^[:space:]]*/\\1${_option}${_defaultValue}/" "${_pamFile}"

    # add 'option=default' if option is not set
	elif grep -q -E "^\\s*${_type}\\s+${_control}\\s+${_module}" < "${_pamFile}" &&
         grep    -E "^\\s*${_type}\\s+${_control}\\s+${_module}" < "${_pamFile}" | grep -q -E -v "\\s${_option}(=|\\s|\$)" ; then

		sed --follow-symlinks -i -E -e "s/^(\\s*${_type}\\s+${_control}\\s+${_module}[^\\n]*)/\\1 ${_option}${_defaultValue}/" "${_pamFile}"
	# add a new entry if none exists
	elif ! grep -q -P "^\\s*${_type}\\s+${_control}\\s+${_module}(\\s.+)?\\s+${_option}${_valueRegex}(\\s|\$)" < "${_pamFile}" ; then
		echo "${_type} ${_control} ${_module} ${_option}${_defaultValue}" >> "${_pamFile}"
	fi
}
ensure_pam_module_options '/etc/pam.d/common-account' 'account' 'required' 'pam_tally2.so' '' '' ''

Complexity:low
Disruption:low
Strategy:configure
- name: Check to see if pam_tally2.so is configured in /etc/pam.d/common-auth
  shell: grep -e '^\s*auth\s\+required\s\+pam_tally2\.so' /etc/pam.d/common-auth ||
    true
  register: check_pam_tally2_result
  tags:
    - CCE-85554-4
    - DISA-STIG-SLES-15-020010
    - accounts_passwords_pam_tally2
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

- name: Configure pam_tally2.so module in /etc/pam.d/common-auth
  lineinfile:
    path: /etc/pam.d/common-auth
    line: auth required pam_tally2.so
    state: present
  when: '"pam_tally2" not in check_pam_tally2_result.stdout'
  tags:
    - CCE-85554-4
    - DISA-STIG-SLES-15-020010
    - accounts_passwords_pam_tally2
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

- name: Check to see if 'onerr' parameter is present
  shell: grep -e '^\s*auth\s\+required\s\+pam_tally2\.so.*\sonerr=.*' /etc/pam.d/common-auth
    || true
  register: check_onerr_result
  tags:
    - CCE-85554-4
    - DISA-STIG-SLES-15-020010
    - accounts_passwords_pam_tally2
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

- name: Make sure pam_tally2.so has 'onerr' parameter set 'fail'
  replace:
    path: /etc/pam.d/common-auth
    regexp: ^(\s*auth\s+required\s+pam_tally2\.so\s+[^\n]*)(onerr=[A-Za-z]+)([^A-Za-z]?.*)
    replace: \1onerr=fail\3
  register: onerr_update_result
  when: '"onerr=" in check_onerr_result.stdout'
  tags:
    - CCE-85554-4
    - DISA-STIG-SLES-15-020010
    - accounts_passwords_pam_tally2
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

- name: Add 'onerr' parameter for pam_tally2.so module in /etc/pam.d/common-auth
  lineinfile:
    path: /etc/pam.d/common-auth
    regexp: ^(\s*auth\s+required\s+pam_tally2\.so)((\s+\S+)*\s*(\\)*$)
    line: \1 onerr=fail\2
    backrefs: true
    state: present
  when: '"onerr=" not in check_onerr_result.stdout'
  tags:
    - CCE-85554-4
    - DISA-STIG-SLES-15-020010
    - accounts_passwords_pam_tally2
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

- name: Check to see if 'deny' parameter is present
  shell: grep -e '^\s*auth\s\+required\s\+pam_tally2\.so.*\sdeny=.*' /etc/pam.d/common-auth
    || true
  register: check_deny_result
  tags:
    - CCE-85554-4
    - DISA-STIG-SLES-15-020010
    - accounts_passwords_pam_tally2
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

- name: Make sure pam_tally2.so has 'deny' parameter set to less than 4
  replace:
    path: /etc/pam.d/common-auth
    regexp: ^(\s*auth\s+required\s+pam_tally2\.so\s+[^\n]*)deny=([4-9]|[1-9][0-9]+)(\s*.*)
    replace: \1deny=3\3
  when: '"deny=" in check_deny_result.stdout'
  tags:
    - CCE-85554-4
    - DISA-STIG-SLES-15-020010
    - accounts_passwords_pam_tally2
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

- name: Add 'deny' parameter for pam_tally2.so module in /etc/pam.d/common-auth
  lineinfile:
    path: /etc/pam.d/common-auth
    regexp: ^(\s*auth\s+required\s+pam_tally2\.so)((\s+\S+)*\s*(\\)*$)
    line: \1 deny=3\2
    backrefs: true
    state: present
  when: '"deny=" not in check_deny_result.stdout'
  tags:
    - CCE-85554-4
    - DISA-STIG-SLES-15-020010
    - accounts_passwords_pam_tally2
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

- name: Check to see if pam_tally2.so is configured in /etc/pam.d/common-account
  shell: grep -e '^\s*account\s\+required\s\+pam_tally2\.so' /etc/pam.d/common-account
    || true
  register: check_account_pam_tally2_result
  tags:
    - CCE-85554-4
    - DISA-STIG-SLES-15-020010
    - accounts_passwords_pam_tally2
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

- name: Configure pam_tally2.so module in /etc/pam.d/common-account
  lineinfile:
    path: /etc/pam.d/common-account
    line: account required pam_tally2.so
    state: present
  when: '"pam_tally2" not in check_account_pam_tally2_result.stdout'
  tags:
    - CCE-85554-4
    - DISA-STIG-SLES-15-020010
    - accounts_passwords_pam_tally2
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
Group   Set Password Quality Requirements   Group contains 1 group and 6 rules
[ref]   The default pam_pwquality PAM module provides strength checking for passwords. It performs a number of checks, such as making sure passwords are not similar to dictionary words, are of at least a certain length, are not the previous password reversed, and are not simply a change of case from the previous password. It can also require passwords to be in certain character classes. The pam_pwquality module is the preferred way of configuring password requirements.

The man pages pam_pwquality(8) provide information on the capabilities and configuration of each.
Group   Set Password Quality Requirements, if using pam_cracklib   Group contains 6 rules
[ref]   The pam_cracklib PAM module can be configured to meet requirements for a variety of policies.

For example, to configure pam_cracklib to require at least one uppercase character, lowercase character, digit, and other (special) character, locate the following line in /etc/pam.d/system-auth:
password requisite pam_cracklib.so try_first_pass retry=3
and then alter it to read:
password required pam_cracklib.so try_first_pass retry=3 maxrepeat=3 minlen=14 dcredit=-1 ucredit=-1 ocredit=-1 lcredit=-1 difok=4
If no such line exists, add one as the first line of the password section in /etc/pam.d/system-auth. The arguments can be modified to ensure compliance with your organization's security policy. Discussion of each parameter follows.
Warning:  Note that the password quality requirements are not enforced for the root account for some reason.

Rule   Set Password Strength Minimum Digit Characters   [ref]

The pam_cracklib module's dcredit parameter controls requirements for usage of digits in a password. When set to a negative number, any password will be required to contain that many digits. When set to a positive number, pam_cracklib will grant +1 additional length credit for each digit. Add dcredit=-1 after pam_cracklib.so to require use of a digit in passwords.
Rationale:
Requiring digits makes password guessing attacks more difficult by ensuring a larger search space.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_cracklib_accounts_password_pam_dcredit
Identifiers and References

Identifiers:  CCE-85564-3

References:  CCI-000194, SRG-OS-000071-GPOS-00039, SLES-15-020150, SV-234884r622137_rule


Complexity:low
Disruption:low
Strategy:restrict
- name: XCCDF Value var_password_pam_dcredit # promote to variable
  set_fact:
    var_password_pam_dcredit: !!str -1
  tags:
    - always

- name: Set control_flag fact
  set_fact:
    control_flag: requisite
  tags:
    - CCE-85564-3
    - DISA-STIG-SLES-15-020150
    - cracklib_accounts_password_pam_dcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check to see if 'pam_cracklib.so' module is configured in '/etc/pam.d/common-password'
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+\S+\s+pam_cracklib.so' /etc/pam.d/common-password || true
  register: check_pam_module_result
  tags:
    - CCE-85564-3
    - DISA-STIG-SLES-15-020150
    - cracklib_accounts_password_pam_dcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Configure 'pam_cracklib.so' module in '/etc/pam.d/common-password'
  lineinfile:
    path: /etc/pam.d/common-password
    line: password requisite pam_cracklib.so
    state: present
  when: '"pam_cracklib.so" not in check_pam_module_result.stdout'
  tags:
    - CCE-85564-3
    - DISA-STIG-SLES-15-020150
    - cracklib_accounts_password_pam_dcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure 'pam_cracklib.so' module has conforming control flag
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+)\S+(\s+pam_cracklib.so\s+.*)
    line: \g<1>requisite\g<2>
    backrefs: true
  when: control_flag|length
  tags:
    - CCE-85564-3
    - DISA-STIG-SLES-15-020150
    - cracklib_accounts_password_pam_dcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure "pam_cracklib.so" module has argument "dcredit={{ var_password_pam_dcredit
    }}"
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_cracklib.so(?:\s+\S+)*\s+dcredit=)(?:\S+)((\s+\S+)*\s*\\*\s*)$
    line: \g<1>{{ var_password_pam_dcredit }}\g<2>
    backrefs: true
  tags:
    - CCE-85564-3
    - DISA-STIG-SLES-15-020150
    - cracklib_accounts_password_pam_dcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check the presence of "dcredit" argument in "pam_cracklib.so" module
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+requisite\s+pam_cracklib.so.*\s+dcredit(=|\s|\s*$)' /etc/pam.d/common-password || true
  register: check_pam_module_argument_result
  tags:
    - CCE-85564-3
    - DISA-STIG-SLES-15-020150
    - cracklib_accounts_password_pam_dcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Add "dcredit" argument to "pam_cracklib.so" module
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_cracklib.so)((\s+\S+)*\s*(\\)*$)
    line: \g<1> dcredit={{ var_password_pam_dcredit }}\g<2>
    backrefs: true
  when: '"dcredit" not in check_pam_module_argument_result.stdout'
  tags:
    - CCE-85564-3
    - DISA-STIG-SLES-15-020150
    - cracklib_accounts_password_pam_dcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Rule   Set Password Strength Minimum Lowercase Characters   [ref]

The pam_cracklib module's lcredit= parameter controls requirements for usage of lowercase letters in a password. When set to a negative number, any password will be required to contain that many lowercase characters. When set to a positive number, pam_cracklib will grant +1 additional length credit for each lowercase character. Add lcredit=-1 after pam_cracklib.so to require use of a lowercase character in passwords.
Rationale:
Requiring a minimum number of lowercase characters makes password guessing attacks more difficult by ensuring a larger search space.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_cracklib_accounts_password_pam_lcredit
Identifiers and References

Identifiers:  CCE-85676-5

References:  CCI-000193, IA-5(1)(a), IA-5(1).1(v), SRG-OS-000070-GPOS-00038, SLES-15-020140, SV-234883r622137_rule


Complexity:low
Disruption:low
Strategy:restrict
- name: XCCDF Value var_password_pam_lcredit # promote to variable
  set_fact:
    var_password_pam_lcredit: !!str -1
  tags:
    - always

- name: Set control_flag fact
  set_fact:
    control_flag: requisite
  tags:
    - CCE-85676-5
    - DISA-STIG-SLES-15-020140
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(1).1(v)
    - cracklib_accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check to see if 'pam_cracklib.so' module is configured in '/etc/pam.d/common-password'
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+\S+\s+pam_cracklib.so' /etc/pam.d/common-password || true
  register: check_pam_module_result
  tags:
    - CCE-85676-5
    - DISA-STIG-SLES-15-020140
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(1).1(v)
    - cracklib_accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Configure 'pam_cracklib.so' module in '/etc/pam.d/common-password'
  lineinfile:
    path: /etc/pam.d/common-password
    line: password requisite pam_cracklib.so
    state: present
  when: '"pam_cracklib.so" not in check_pam_module_result.stdout'
  tags:
    - CCE-85676-5
    - DISA-STIG-SLES-15-020140
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(1).1(v)
    - cracklib_accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure 'pam_cracklib.so' module has conforming control flag
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+)\S+(\s+pam_cracklib.so\s+.*)
    line: \g<1>requisite\g<2>
    backrefs: true
  when: control_flag|length
  tags:
    - CCE-85676-5
    - DISA-STIG-SLES-15-020140
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(1).1(v)
    - cracklib_accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure "pam_cracklib.so" module has argument "lcredit={{ var_password_pam_lcredit
    }}"
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_cracklib.so(?:\s+\S+)*\s+lcredit=)(?:\S+)((\s+\S+)*\s*\\*\s*)$
    line: \g<1>{{ var_password_pam_lcredit }}\g<2>
    backrefs: true
  tags:
    - CCE-85676-5
    - DISA-STIG-SLES-15-020140
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(1).1(v)
    - cracklib_accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check the presence of "lcredit" argument in "pam_cracklib.so" module
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+requisite\s+pam_cracklib.so.*\s+lcredit(=|\s|\s*$)' /etc/pam.d/common-password || true
  register: check_pam_module_argument_result
  tags:
    - CCE-85676-5
    - DISA-STIG-SLES-15-020140
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(1).1(v)
    - cracklib_accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Add "lcredit" argument to "pam_cracklib.so" module
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_cracklib.so)((\s+\S+)*\s*(\\)*$)
    line: \g<1> lcredit={{ var_password_pam_lcredit }}\g<2>
    backrefs: true
  when: '"lcredit" not in check_pam_module_argument_result.stdout'
  tags:
    - CCE-85676-5
    - DISA-STIG-SLES-15-020140
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(1).1(v)
    - cracklib_accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Rule   Set Password Minimum Length   [ref]

The pam_cracklib module's minlen parameter controls requirements for minimum characters required in a password. Add minlen=14 to set minimum password length requirements.
Rationale:
Password length is one factor of several that helps to determine strength and how long it takes to crack a password. Use of more characters in a password helps to exponentially increase the time and/or resources required to compromise the password.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_cracklib_accounts_password_pam_minlen
Identifiers and References

Identifiers:  CCE-85573-4

References:  CCI-000205, SRG-OS-000078-GPOS-00046, SLES-15-020260, SV-234895r622137_rule


Complexity:low
Disruption:low
Strategy:restrict
- name: XCCDF Value var_password_pam_minlen # promote to variable
  set_fact:
    var_password_pam_minlen: !!str 14
  tags:
    - always

- name: Set control_flag fact
  set_fact:
    control_flag: requisite
  tags:
    - CCE-85573-4
    - DISA-STIG-SLES-15-020260
    - cracklib_accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check to see if 'pam_cracklib.so' module is configured in '/etc/pam.d/common-password'
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+\S+\s+pam_cracklib.so' /etc/pam.d/common-password || true
  register: check_pam_module_result
  tags:
    - CCE-85573-4
    - DISA-STIG-SLES-15-020260
    - cracklib_accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Configure 'pam_cracklib.so' module in '/etc/pam.d/common-password'
  lineinfile:
    path: /etc/pam.d/common-password
    line: password requisite pam_cracklib.so
    state: present
  when: '"pam_cracklib.so" not in check_pam_module_result.stdout'
  tags:
    - CCE-85573-4
    - DISA-STIG-SLES-15-020260
    - cracklib_accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure 'pam_cracklib.so' module has conforming control flag
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+)\S+(\s+pam_cracklib.so\s+.*)
    line: \g<1>requisite\g<2>
    backrefs: true
  when: control_flag|length
  tags:
    - CCE-85573-4
    - DISA-STIG-SLES-15-020260
    - cracklib_accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure "pam_cracklib.so" module has argument "minlen={{ var_password_pam_minlen
    }}"
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_cracklib.so(?:\s+\S+)*\s+minlen=)(?:\S+)((\s+\S+)*\s*\\*\s*)$
    line: \g<1>{{ var_password_pam_minlen }}\g<2>
    backrefs: true
  tags:
    - CCE-85573-4
    - DISA-STIG-SLES-15-020260
    - cracklib_accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check the presence of "minlen" argument in "pam_cracklib.so" module
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+requisite\s+pam_cracklib.so.*\s+minlen(=|\s|\s*$)' /etc/pam.d/common-password || true
  register: check_pam_module_argument_result
  tags:
    - CCE-85573-4
    - DISA-STIG-SLES-15-020260
    - cracklib_accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Add "minlen" argument to "pam_cracklib.so" module
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_cracklib.so)((\s+\S+)*\s*(\\)*$)
    line: \g<1> minlen={{ var_password_pam_minlen }}\g<2>
    backrefs: true
  when: '"minlen" not in check_pam_module_argument_result.stdout'
  tags:
    - CCE-85573-4
    - DISA-STIG-SLES-15-020260
    - cracklib_accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Rule   Set Password Strength Minimum Special Characters   [ref]

The pam_cracklib module's ocredit= parameter controls requirements for usage of special (or ``other'') characters in a password. When set to a negative number, any password will be required to contain that many special characters. When set to a positive number, pam_cracklib will grant +1 additional length credit for each special character. Make sure the ocredit parameter for the pam_cracklib module is set to less than or equal to -1. For example, ocredit=-1.
Rationale:
Requiring a minimum number of special characters makes password guessing attacks more difficult by ensuring a larger search space.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_cracklib_accounts_password_pam_ocredit
Identifiers and References

Identifiers:  CCE-85574-2

References:  CCI-001619, IA-5(a), IA-5(v), SRG-OS-000266-GPOS-00101, SLES-15-020270, SV-234896r622137_rule


Complexity:low
Disruption:low
Strategy:restrict
- name: XCCDF Value var_password_pam_ocredit # promote to variable
  set_fact:
    var_password_pam_ocredit: !!str -1
  tags:
    - always

- name: Set control_flag fact
  set_fact:
    control_flag: requisite
  tags:
    - CCE-85574-2
    - DISA-STIG-SLES-15-020270
    - NIST-800-53-IA-5(a)
    - NIST-800-53-IA-5(v)
    - cracklib_accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check to see if 'pam_cracklib.so' module is configured in '/etc/pam.d/common-password'
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+\S+\s+pam_cracklib.so' /etc/pam.d/common-password || true
  register: check_pam_module_result
  tags:
    - CCE-85574-2
    - DISA-STIG-SLES-15-020270
    - NIST-800-53-IA-5(a)
    - NIST-800-53-IA-5(v)
    - cracklib_accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Configure 'pam_cracklib.so' module in '/etc/pam.d/common-password'
  lineinfile:
    path: /etc/pam.d/common-password
    line: password requisite pam_cracklib.so
    state: present
  when: '"pam_cracklib.so" not in check_pam_module_result.stdout'
  tags:
    - CCE-85574-2
    - DISA-STIG-SLES-15-020270
    - NIST-800-53-IA-5(a)
    - NIST-800-53-IA-5(v)
    - cracklib_accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure 'pam_cracklib.so' module has conforming control flag
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+)\S+(\s+pam_cracklib.so\s+.*)
    line: \g<1>requisite\g<2>
    backrefs: true
  when: control_flag|length
  tags:
    - CCE-85574-2
    - DISA-STIG-SLES-15-020270
    - NIST-800-53-IA-5(a)
    - NIST-800-53-IA-5(v)
    - cracklib_accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure "pam_cracklib.so" module has argument "ocredit={{ var_password_pam_ocredit
    }}"
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_cracklib.so(?:\s+\S+)*\s+ocredit=)(?:\S+)((\s+\S+)*\s*\\*\s*)$
    line: \g<1>{{ var_password_pam_ocredit }}\g<2>
    backrefs: true
  tags:
    - CCE-85574-2
    - DISA-STIG-SLES-15-020270
    - NIST-800-53-IA-5(a)
    - NIST-800-53-IA-5(v)
    - cracklib_accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check the presence of "ocredit" argument in "pam_cracklib.so" module
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+requisite\s+pam_cracklib.so.*\s+ocredit(=|\s|\s*$)' /etc/pam.d/common-password || true
  register: check_pam_module_argument_result
  tags:
    - CCE-85574-2
    - DISA-STIG-SLES-15-020270
    - NIST-800-53-IA-5(a)
    - NIST-800-53-IA-5(v)
    - cracklib_accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Add "ocredit" argument to "pam_cracklib.so" module
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_cracklib.so)((\s+\S+)*\s*(\\)*$)
    line: \g<1> ocredit={{ var_password_pam_ocredit }}\g<2>
    backrefs: true
  when: '"ocredit" not in check_pam_module_argument_result.stdout'
  tags:
    - CCE-85574-2
    - DISA-STIG-SLES-15-020270
    - NIST-800-53-IA-5(a)
    - NIST-800-53-IA-5(v)
    - cracklib_accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Rule   Set Password Retry Limit   [ref]

The pam_cracklib module's retry parameter controls the maximum number of times to prompt the user for the password before returning with error. Make sure it is configured with a value that is no more than 3. For example, retry=1.
Rationale:
To reduce opportunities for successful guesses and brute-force attacks.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_cracklib_accounts_password_pam_retry
Identifiers and References

Identifiers:  CCE-85575-9

References:  CCI-000366, SRG-OS-000480-GPOS-00225, SLES-15-020290, SV-234897r622137_rule


Complexity:low
Disruption:low
Strategy:restrict
- name: XCCDF Value var_password_pam_retry # promote to variable
  set_fact:
    var_password_pam_retry: !!str 3
  tags:
    - always

- name: Set control_flag fact
  set_fact:
    control_flag: requisite
  tags:
    - CCE-85575-9
    - DISA-STIG-SLES-15-020290
    - cracklib_accounts_password_pam_retry
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check to see if 'pam_cracklib.so' module is configured in '/etc/pam.d/common-password'
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+\S+\s+pam_cracklib.so' /etc/pam.d/common-password || true
  register: check_pam_module_result
  tags:
    - CCE-85575-9
    - DISA-STIG-SLES-15-020290
    - cracklib_accounts_password_pam_retry
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Configure 'pam_cracklib.so' module in '/etc/pam.d/common-password'
  lineinfile:
    path: /etc/pam.d/common-password
    line: password requisite pam_cracklib.so
    state: present
  when: '"pam_cracklib.so" not in check_pam_module_result.stdout'
  tags:
    - CCE-85575-9
    - DISA-STIG-SLES-15-020290
    - cracklib_accounts_password_pam_retry
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure 'pam_cracklib.so' module has conforming control flag
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+)\S+(\s+pam_cracklib.so\s+.*)
    line: \g<1>requisite\g<2>
    backrefs: true
  when: control_flag|length
  tags:
    - CCE-85575-9
    - DISA-STIG-SLES-15-020290
    - cracklib_accounts_password_pam_retry
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure "pam_cracklib.so" module has argument "retry={{ var_password_pam_retry
    }}"
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_cracklib.so(?:\s+\S+)*\s+retry=)(?:\S+)((\s+\S+)*\s*\\*\s*)$
    line: \g<1>{{ var_password_pam_retry }}\g<2>
    backrefs: true
  tags:
    - CCE-85575-9
    - DISA-STIG-SLES-15-020290
    - cracklib_accounts_password_pam_retry
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check the presence of "retry" argument in "pam_cracklib.so" module
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+requisite\s+pam_cracklib.so.*\s+retry(=|\s|\s*$)' /etc/pam.d/common-password || true
  register: check_pam_module_argument_result
  tags:
    - CCE-85575-9
    - DISA-STIG-SLES-15-020290
    - cracklib_accounts_password_pam_retry
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Add "retry" argument to "pam_cracklib.so" module
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_cracklib.so)((\s+\S+)*\s*(\\)*$)
    line: \g<1> retry={{ var_password_pam_retry }}\g<2>
    backrefs: true
  when: '"retry" not in check_pam_module_argument_result.stdout'
  tags:
    - CCE-85575-9
    - DISA-STIG-SLES-15-020290
    - cracklib_accounts_password_pam_retry
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Rule   Set Password Strength Minimum Uppercase Characters   [ref]

The pam_cracklib module's ucredit= parameter controls requirements for usage of uppercase letters in a password. When set to a negative number, any password will be required to contain that many uppercase characters. When set to a positive number, pam_cracklib will grant +1 additional length credit for each uppercase character. Add ucredit=-1 after pam_cracklib.so to require use of an upper case character in passwords.
Rationale:
Requiring a minimum number of uppercase characters makes password guessing attacks more difficult by ensuring a larger search space.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_cracklib_accounts_password_pam_ucredit
Identifiers and References

Identifiers:  CCE-85675-7

References:  CCI-000192, IA-5(1)(a), IA-5(1).1(v), SRG-OS-000069-GPOS-00037, SLES-15-020130, SV-234882r622137_rule


Complexity:low
Disruption:low
Strategy:restrict
- name: XCCDF Value var_password_pam_ucredit # promote to variable
  set_fact:
    var_password_pam_ucredit: !!str -1
  tags:
    - always

- name: Set control_flag fact
  set_fact:
    control_flag: requisite
  tags:
    - CCE-85675-7
    - DISA-STIG-SLES-15-020130
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(1).1(v)
    - cracklib_accounts_password_pam_ucredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check to see if 'pam_cracklib.so' module is configured in '/etc/pam.d/common-password'
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+\S+\s+pam_cracklib.so' /etc/pam.d/common-password || true
  register: check_pam_module_result
  tags:
    - CCE-85675-7
    - DISA-STIG-SLES-15-020130
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(1).1(v)
    - cracklib_accounts_password_pam_ucredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Configure 'pam_cracklib.so' module in '/etc/pam.d/common-password'
  lineinfile:
    path: /etc/pam.d/common-password
    line: password requisite pam_cracklib.so
    state: present
  when: '"pam_cracklib.so" not in check_pam_module_result.stdout'
  tags:
    - CCE-85675-7
    - DISA-STIG-SLES-15-020130
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(1).1(v)
    - cracklib_accounts_password_pam_ucredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure 'pam_cracklib.so' module has conforming control flag
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+)\S+(\s+pam_cracklib.so\s+.*)
    line: \g<1>requisite\g<2>
    backrefs: true
  when: control_flag|length
  tags:
    - CCE-85675-7
    - DISA-STIG-SLES-15-020130
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(1).1(v)
    - cracklib_accounts_password_pam_ucredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Ensure "pam_cracklib.so" module has argument "ucredit={{ var_password_pam_ucredit
    }}"
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_cracklib.so(?:\s+\S+)*\s+ucredit=)(?:\S+)((\s+\S+)*\s*\\*\s*)$
    line: \g<1>{{ var_password_pam_ucredit }}\g<2>
    backrefs: true
  tags:
    - CCE-85675-7
    - DISA-STIG-SLES-15-020130
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(1).1(v)
    - cracklib_accounts_password_pam_ucredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check the presence of "ucredit" argument in "pam_cracklib.so" module
  shell: |
    set -o pipefail
    grep -E '^\s*password\s+requisite\s+pam_cracklib.so.*\s+ucredit(=|\s|\s*$)' /etc/pam.d/common-password || true
  register: check_pam_module_argument_result
  tags:
    - CCE-85675-7
    - DISA-STIG-SLES-15-020130
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(1).1(v)
    - cracklib_accounts_password_pam_ucredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Add "ucredit" argument to "pam_cracklib.so" module
  lineinfile:
    path: /etc/pam.d/common-password
    regexp: ^(\s*password\s+requisite\s+pam_cracklib.so)((\s+\S+)*\s*(\\)*$)
    line: \g<1> ucredit={{ var_password_pam_ucredit }}\g<2>
    backrefs: true
  when: '"ucredit" not in check_pam_module_argument_result.stdout'
  tags:
    - CCE-85675-7
    - DISA-STIG-SLES-15-020130
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(1).1(v)
    - cracklib_accounts_password_pam_ucredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
Group   Set Password Hashing Algorithm   Group contains 1 rule
[ref]   The system's default algorithm for storing password hashes in /etc/shadow is SHA-512. This can be configured in several locations.

Rule   Set Password Hashing Algorithm in /etc/login.defs   [ref]

In /etc/login.defs, add or correct the following line to ensure the system will use SHA-512 as the hashing algorithm:
ENCRYPT_METHOD SHA512
Rationale:
Passwords need to be protected at all times, and encryption is the standard method for protecting passwords. If passwords are not encrypted, they can be plainly read (i.e., clear text) and easily compromised. Passwords that are encrypted with a weak algorithm are no more protected than if they are kept in plain text.

Using a stronger hashing algorithm makes password cracking attacks more difficult.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_set_password_hashing_algorithm_logindefs
Identifiers and References

Identifiers:  CCE-83279-0

References:  BP28(R32), 1, 12, 15, 16, 5, 5.6.2.2, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, 3.13.11, CCI-000196, 4.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, SR 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, 0418, 1055, 1402, A.18.1.4, 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, IA-5(c), IA-5(1)(c), CM-6(a), PR.AC-1, PR.AC-6, PR.AC-7, Req-8.2.1, SRG-OS-000073-GPOS-00041, SLES-15-010260, SV-234825r622137_rule


Complexity:low
Disruption:low
Strategy:restrict
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
    - CCE-83279-0
    - CJIS-5.6.2.2
    - DISA-STIG-SLES-15-010260
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.1
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - set_password_hashing_algorithm_logindefs
- name: XCCDF Value var_password_hashing_algorithm # promote to variable
  set_fact:
    var_password_hashing_algorithm: !!str SHA512
  tags:
    - always

- name: Set Password Hashing Algorithm in /etc/login.defs
  lineinfile:
    dest: /etc/login.defs
    regexp: ^#?ENCRYPT_METHOD
    line: ENCRYPT_METHOD {{ var_password_hashing_algorithm }}
    state: present
    create: true
  when: '"shadow" in ansible_facts.packages'
  tags:
    - CCE-83279-0
    - CJIS-5.6.2.2
    - DISA-STIG-SLES-15-010260
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.1
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - set_password_hashing_algorithm_logindefs
Group   Protect Physical Console Access   Group contains 2 rules
[ref]   It is impossible to fully protect a system from an attacker with physical access, so securing the space in which the system is located should be considered a necessary step. However, there are some steps which, if taken, make it more difficult for an attacker to quickly or undetectably modify a system from its console.

Rule   Require Authentication for Emergency Systemd Target   [ref]

Emergency mode is intended as a system recovery method, providing a single user root access to the system during a failed boot sequence.

By default, Emergency mode is protected by requiring a password and is set in /usr/lib/systemd/system/emergency.service.
Rationale:
This prevents attackers with physical access from trivially bypassing security on the machine and gaining root access. Such accesses are further prevented by configuring the bootloader password.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_require_emergency_target_auth
Identifiers and References

References:  1, 11, 12, 14, 15, 16, 18, 3, 5, DSS05.02, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.06, DSS06.10, 3.1.1, 3.4.5, CCI-000213, 164.308(a)(1)(ii)(B), 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.310(a)(1), 164.310(a)(2)(i), 164.310(a)(2)(ii), 164.310(a)(2)(iii), 164.310(b), 164.310(c), 164.310(d)(1), 164.310(d)(2)(iii), 4.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, SR 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, 0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561, A.18.1.4, A.6.1.2, 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, IA-2, AC-3, CM-6(a), PR.AC-1, PR.AC-4, PR.AC-6, PR.AC-7, PR.PT-3, FIA_UAU.1, SRG-OS-000080-GPOS-00048


Complexity:low
Disruption:low
Strategy:restrict
- name: require emergency mode password
  lineinfile:
    create: true
    dest: /usr/lib/systemd/system/emergency.service
    regexp: ^#?ExecStart=
    line: ExecStart=-/bin/sh -c "/sbin/sulogin; /usr/bin/systemctl --fail --no-block
      default"
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - NIST-800-171-3.1.1
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - require_emergency_target_auth
    - restrict_strategy

Rule   Require Authentication for Single User Mode   [ref]

Single-user mode is intended as a system recovery method, providing a single user root access to the system by providing a boot option at startup. By default, no authentication is performed if single-user mode is selected.

By default, single-user mode is protected by requiring a password and is set in /usr/lib/systemd/system/rescue.service.
Rationale:
This prevents attackers with physical access from trivially bypassing security on the machine and gaining root access. Such accesses are further prevented by configuring the bootloader password.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_require_singleuser_auth
Identifiers and References

References:  1, 11, 12, 14, 15, 16, 18, 3, 5, DSS05.02, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.06, DSS06.10, 3.1.1, 3.4.5, CCI-000213, 164.308(a)(1)(ii)(B), 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.310(a)(1), 164.310(a)(2)(i), 164.310(a)(2)(ii), 164.310(a)(2)(iii), 164.310(b), 164.310(c), 164.310(d)(1), 164.310(d)(2)(iii), 4.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, SR 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, 0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561, A.18.1.4, A.6.1.2, 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, CIP-003-3 R5.1.1, CIP-003-3 R5.3, CIP-004-3 R2.2.3, CIP-004-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.2, CIP-007-3 R5.2, CIP-007-3 R5.3.1, CIP-007-3 R5.3.2, CIP-007-3 R5.3.3, IA-2, AC-3, CM-6(a), PR.AC-1, PR.AC-4, PR.AC-6, PR.AC-7, PR.PT-3, FIA_UAU.1, SRG-OS-000080-GPOS-00048


Complexity:low
Disruption:low
Strategy:restrict
- name: require single user mode password
  lineinfile:
    create: true
    dest: /usr/lib/systemd/system/rescue.service
    regexp: ^#?ExecStart=
    line: ExecStart=-/bin/sh -c "/sbin/sulogin; /usr/bin/systemctl --fail --no-block
      default"
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - NIST-800-171-3.1.1
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - require_singleuser_auth
    - restrict_strategy
Group   Protect Accounts by Restricting Password-Based Login   Group contains 3 groups and 6 rules
[ref]   Conventionally, Unix shell accounts are accessed by providing a username and password to a login program, which tests these values for correctness using the /etc/passwd and /etc/shadow files. Password-based login is vulnerable to guessing of weak passwords, and to sniffing and man-in-the-middle attacks against passwords entered over a network or at an insecure console. Therefore, mechanisms for accessing accounts by entering usernames and passwords should be restricted to those which are operationally necessary.
Group   Set Password Expiration Parameters   Group contains 3 rules
[ref]   The file /etc/login.defs controls several password-related settings. Programs such as passwd, su, and login consult /etc/login.defs to determine behavior with regard to password aging, expiration warnings, and length. See the man page login.defs(5) for more information.

Users should be forced to change their passwords, in order to decrease the utility of compromised passwords. However, the need to change passwords often should be balanced against the risk that users will reuse or write down passwords if forced to change them too often. Forcing password changes every 90-360 days, depending on the environment, is recommended. Set the appropriate value as PASS_MAX_DAYS and apply it to existing accounts with the -M flag.

The PASS_MIN_DAYS (-m) setting prevents password changes for 7 days after the first change, to discourage password cycling. If you use this setting, train users to contact an administrator for an emergency password change in case a new password becomes compromised. The PASS_WARN_AGE (-W) setting gives users 7 days of warnings at login time that their passwords are about to expire.

For example, for each existing human user USER, expiration parameters could be adjusted to a 180 day maximum password age, 7 day minimum password age, and 7 day warning period with the following command:
$ sudo chage -M 180 -m 7 -W 7 USER
Group   Verify Proper Storage and Existence of Password Hashes   Group contains 1 rule
[ref]   By default, password hashes for local accounts are stored in the second field (colon-separated) in /etc/shadow. This file should be readable only by processes running with root credentials, preventing users from casually accessing others' password hashes and attempting to crack them. However, it remains possible to misconfigure the system and store password hashes in world-readable files such as /etc/passwd, or to even store passwords themselves in plaintext on the system. Using system-provided tools for password change/creation should allow administrators to avoid such misconfiguration.

Rule   All GIDs referenced in /etc/passwd must be defined in /etc/group   [ref]

Add a group to the system for each GID referenced without a corresponding group.
Rationale:
If a user is assigned the Group Identifier (GID) of a group not existing on the system, and a group with the Gruop Identifier (GID) is subsequently created, the user may have unintended rights to any files associated with the group.
Severity: 
low
Rule ID:xccdf_org.ssgproject.content_rule_gid_passwd_group_same
Identifiers and References

References:  1, 12, 15, 16, 5, 5.5.2, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-000764, 4.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, SR 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, A.18.1.4, 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, CIP-003-3 R5.1.1, CIP-003-3 R5.3, CIP-004-3 R2.2.3, CIP-004-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.2, CIP-007-3 R5.2, CIP-007-3 R5.3.1, CIP-007-3 R5.3.2, CIP-007-3 R5.3.3, IA-2, CM-6(a), PR.AC-1, PR.AC-6, PR.AC-7, Req-8.5.a, SRG-OS-000104-GPOS-00051, 6.2.13

Group   Restrict Root Logins   Group contains 2 rules
[ref]   Direct root logins should be allowed only for emergency use. In normal situations, the administrator should access the system via a unique unprivileged account, and then use su or sudo to execute privileged commands. Discouraging administrators from accessing the root account directly ensures an audit trail in organizations with multiple administrators. Locking down the channels through which root can connect directly also reduces opportunities for password-guessing against the root account. The login program uses the file /etc/securetty to determine which interfaces should allow root logins. The virtual devices /dev/console and /dev/tty* represent the system consoles (accessible via the Ctrl-Alt-F1 through Ctrl-Alt-F6 keyboard sequences on a default installation). The default securetty file also contains /dev/vc/*. These are likely to be deprecated in most environments, but may be retained for compatibility. Root should also be prohibited from connecting via network protocols. Other sections of this document include guidance describing how to prevent root from logging in via SSH.

Rule   Enforce usage of pam_wheel for su authentication   [ref]

To ensure that only users who are members of the wheel group can run commands with altered privileges through the su command, make sure that the following line exists in the file /etc/pam.d/su:
auth             required        pam_wheel.so use_uid
Rationale:
The su program allows to run commands with a substitute user and group ID. It is commonly used to run commands as the root user. Limiting access to such command is considered a good security practice.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_use_pam_wheel_for_su
Identifiers and References

References:  FMT_SMF_EXT.1.1, SRG-OS-000373-GPOS-00156, SRG-OS-000312-GPOS-00123, 5.6

Group   Secure Session Configuration Files for Login Accounts   Group contains 1 group and 8 rules
[ref]   When a user logs into a Unix account, the system configures the user's session by reading a number of files. Many of these files are located in the user's home directory, and may have weak permissions as a result of user error or misconfiguration. If an attacker can modify or even read certain types of account configuration information, they can often gain full access to the affected user's account. Therefore, it is important to test and correct configuration file permissions for interactive accounts, particularly those of privileged users such as root or system administrators.
Group   Ensure that Users Have Sensible Umask Values   Group contains 4 rules
[ref]   The umask setting controls the default permissions for the creation of new files. With a default umask setting of 077, files and directories created by users will not be readable by any other user on the system. Users who wish to make specific files group- or world-readable can accomplish this by using the chmod command. Additionally, users can make all their files readable to their group by default by setting a umask of 027 in their shell configuration files. If default per-user groups exist (that is, if every user has a default group whose name is the same as that user's username and whose only member is the user), then it may even be safe for users to select a umask of 007, making it very easy to intentionally share files with groups of which the user is a member.

Rule   Ensure the Default Bash Umask is Set Correctly   [ref]

To ensure the default umask for users of the Bash shell is set properly, add or correct the umask setting in /etc/bashrc to read as follows:
umask 027
Rationale:
The umask value influences the permissions assigned to files when they are created. A misconfigured umask value could result in files with excessive permissions that can be read or written to by unauthorized users.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_umask_etc_bashrc
Identifiers and References

References:  BP28(R35), 18, APO13.01, BAI03.01, BAI03.02, BAI03.03, CCI-000366, 4.3.4.3.3, A.14.1.1, A.14.2.1, A.14.2.5, A.6.1.5, CIP-003-3 R5.1.1, CIP-003-3 R5.3, CIP-004-3 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, AC-6(1), CM-6(a), PR.IP-2, SRG-OS-000480-GPOS-00228, SRG-OS-000480-GPOS-00227


Complexity:low
Disruption:low
Strategy:restrict
- name: XCCDF Value var_accounts_user_umask # promote to variable
  set_fact:
    var_accounts_user_umask: !!str 027
  tags:
    - always

- name: Set user umask in /etc/bashrc
  replace:
    path: /etc/bashrc
    regexp: umask.*
    replace: umask {{ var_accounts_user_umask }}
  tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_bashrc
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Rule   Ensure the Default Umask is Set Correctly in /etc/profile   [ref]

To ensure the default umask controlled by /etc/profile is set properly, add or correct the umask setting in /etc/profile to read as follows:
umask 027
Rationale:
The umask value influences the permissions assigned to files when they are created. A misconfigured umask value could result in files with excessive permissions that can be read or written to by unauthorized users.
Severity: 
unknown
Rule ID:xccdf_org.ssgproject.content_rule_accounts_umask_etc_profile
Identifiers and References

References:  BP28(R35), 18, APO13.01, BAI03.01, BAI03.02, BAI03.03, CCI-000366, 4.3.4.3.3, A.14.1.1, A.14.2.1, A.14.2.5, A.6.1.5, CIP-003-3 R5.1.1, CIP-003-3 R5.3, CIP-004-3 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, AC-6(1), CM-6(a), PR.IP-2, SRG-OS-000480-GPOS-00228



var_accounts_user_umask="027"



grep -q umask /etc/profile && \
  sed -i "s/umask.*/umask $var_accounts_user_umask/g" /etc/profile
if ! [ $? -eq 0 ]; then
    echo "umask $var_accounts_user_umask" >> /etc/profile
fi

Complexity:low
Disruption:low
Strategy:restrict
- name: XCCDF Value var_accounts_user_umask # promote to variable
  set_fact:
    var_accounts_user_umask: !!str 027
  tags:
    - always

- name: Set user umask in /etc/profile
  replace:
    path: /etc/profile
    regexp: umask.*
    replace: umask {{ var_accounts_user_umask }}
  tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_profile
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - unknown_severity

Rule   Ensure the Default Umask is Set Correctly For Interactive Users   [ref]

Remove the UMASK environment variable from all interactive users initialization files.
Rationale:
The umask controls the default access mode assigned to newly created files. A umask of 077 limits new files to mode 700 or less permissive. Although umask can be represented as a four-digit number, the first digit representing special access modes is typically ignored or required to be 0. This requirement applies to the globally configured system defaults and the local interactive user defaults for each account on the system.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_umask_interactive_users
Identifiers and References

References:  CCI-000366, CCI-001814, SRG-OS-000480-GPOS-00227

Rule   All Interactive Users Home Directories Must Exist   [ref]

Create home directories to all interactive users that currently do not have a home directory assigned. Use the following commands to create the user home directory assigned in /etc/passwd:
$ sudo mkdir /home/USER
Rationale:
If a local interactive user has a home directory defined that does not exist, the user may be given access to the / directory as the current working directory upon logon. This could create a Denial of Service because the user would not be able to access their logon configuration files, and it may give them visibility to system files they normally would not be able to access.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_user_interactive_home_directory_exists
Identifiers and References

Identifiers:  CCE-85628-6

References:  CCI-000366, SRG-OS-000480-GPOS-00227, SLES-15-040080, SV-234992r622137_rule

Rule   All User Files and Directories In The Home Directory Must Be Group-Owned By The Primary User   [ref]

Change the group of a local interactive users files and directories to a group that the interactive user is a member of. To change the group owner of a local interactive users files and directories, use the following command:
$ sudo chgrp USER_GROUP /home/USER/FILE_DIR
Rationale:
If a local interactive users files are group-owned by a group of which the user is not a member, unintended users may be able to access them.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_users_home_files_groupownership
Identifiers and References

References:  CCI-000366, SRG-OS-000480-GPOS-00227, 6.2.7

Rule   All User Files and Directories In The Home Directory Must Be Owned By The Primary User   [ref]

Change the owner of a interactive users files and directories to that owner. To change the of a local interactive users files and directories, use the following command:
$ sudo chown -R USER /home/USER
Rationale:
If local interactive users do not own the files in their directories, unauthorized users may be able to access them. Additionally, if files are not owned by the user, this could be an indication of system compromise.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_users_home_files_ownership
Identifiers and References

References:  CCI-000366, SRG-OS-000480-GPOS-00227, 6.2.7

Rule   All User Files and Directories In The Home Directory Must Have Mode 0750 Or Less Permissive   [ref]

Set the mode on files and directories in the local interactive user home directory with the following command:
$ sudo chmod 0750 /home/USER/FILE_DIR
Rationale:
If a local interactive user files have excessive permissions, unintended users may be able to access or modify them.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_accounts_users_home_files_permissions
Identifiers and References

References:  CCI-000366, SRG-OS-000480-GPOS-00227, 6.2.6

Group   System Accounting with auditd   Group contains 5 groups and 22 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 Fedora Documentation available at https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#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".
Group   Configure auditd Rules for Comprehensive Auditing   Group contains 3 groups and 13 rules
[ref]   The auditd program can perform comprehensive monitoring of system activity. This section describes recommended configuration settings for comprehensive auditing, but a full description of the auditing system's capabilities is beyond the scope of this guide. The mailing list linux-audit@redhat.com exists to facilitate community discussion of the auditing system.

The audit subsystem supports extensive collection of events, including:
  • Tracing of arbitrary system calls (identified by name or number) on entry or exit.
  • Filtering by PID, UID, call success, system call argument (with some limitations), etc.
  • Monitoring of specific files for modifications to the file's contents or metadata.

Auditing rules at startup are controlled by the file /etc/audit/audit.rules. Add rules to it to meet the auditing requirements for your organization. Each line in /etc/audit/audit.rules represents a series of arguments that can be passed to auditctl and can be individually tested during runtime. See documentation in /usr/share/doc/audit-VERSION and in the related man pages for more details.

If copying any example audit rulesets from /usr/share/doc/audit-VERSION, be sure to comment out the lines containing arch= which are not appropriate for your system's architecture. Then review and understand the following rules, ensuring rules are activated as needed for the appropriate architecture.

After reviewing all the rules, reading the following sections, and editing as needed, the new rules can be activated as follows:
$ sudo service auditd restart
Group   Record Information on Kernel Modules Loading and Unloading   Group contains 1 rule
[ref]   To capture kernel module loading and unloading events, use following lines, setting ARCH to either b32 for 32-bit system, or having two lines for both b32 and b64 in case your system is 64-bit:
-a always,exit -F arch=ARCH -S init_module,delete_module -F key=modules
Place to add the lines depends on a way auditd daemon is configured. If it is configured to use the augenrules program (the default), add the lines to a file with suffix .rules in the directory /etc/audit/rules.d. If the auditd daemon is configured to use the auditctl utility, add the lines to file /etc/audit/audit.rules.

Rule   Ensure auditd Collects Information on Kernel Module Loading and Unloading   [ref]

To capture kernel module loading and unloading events, use following lines, setting ARCH to either b32 for 32-bit system, or having two lines for both b32 and b64 in case your system is 64-bit:
-a always,exit -F arch=ARCH -S init_module,finit_module,delete_module -F key=modules
The place to add the lines depends on a way auditd daemon is configured. If it is configured to use the augenrules program (the default), add the lines to a file with suffix .rules in the directory /etc/audit/rules.d. If the auditd daemon is configured to use the auditctl utility, add the lines to file /etc/audit/audit.rules.
Rationale:
The addition/removal of kernel modules can be used to alter the behavior of the kernel and potentially introduce malicious code into kernel space. It is important to have an audit trail of modules that have been introduced into the kernel.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_audit_rules_kernel_module_loading
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.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, 3.1.7, CCI-000172, 4.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, SR 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, A.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, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.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, Req-10.2.7, 4.1.16


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; then



# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
# Note: 32-bit and 64-bit kernel syscall numbers not always line up =>
#       it's required on a 64-bit system to check also for the presence
#       of 32-bit's equivalent of the corresponding rule.
#       (See `man 7 audit.rules` for details )
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
        GROUP="modules"
        PATTERN="-a always,exit -F arch=$ARCH -S init_module -S delete_module -S finit_module \(-F key=\|-k \).*"
        FULL_RULE="-a always,exit -F arch=$ARCH -S init_module -S delete_module -S finit_module -k modules"
        # Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
# Function to fix syscall audit rule for given system call. It is
# based on example audit syscall rule definitions as outlined in
# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
# package. It will combine multiple system calls belonging to the same
# syscall group into one audit rule (rather than to create audit rule per
# different system call) to avoid audit infrastructure performance penalty
# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
#
#   https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
#
# for further details.
#
# Expects five arguments (each of them is required) in the form of:
# * audit tool				tool used to load audit rules,
# 					either 'auditctl', or 'augenrules
# * audit rules' pattern		audit rule skeleton for same syscall
# * syscall group			greatest common string this rule shares
# 					with other rules from the same group
# * architecture			architecture this rule is intended for
# * full form of new rule to add	expected full form of audit rule as to be
# 					added into audit.rules file
#
# Note: The 2-th up to 4-th arguments are used to determine how many existing
# audit rules will be inspected for resemblance with the new audit rule
# (5-th argument) the function is going to add. The rule's similarity check
# is performed to optimize audit.rules definition (merge syscalls of the same
# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
# penalty.
#
# Example call:
#
#	See e.g. 'audit_rules_file_deletion_events.sh' remediation script
#
function fix_audit_syscall_rule {

# Load function arguments into local variables
local tool="$1"
local pattern="$2"
local group="$3"
local arch="$4"
local full_rule="$5"

# Check sanity of the input
if [ $# -ne "5" ]
then
	echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
	echo "Aborting."
	exit 1
fi

# Create a list of audit *.rules files that should be inspected for presence and correctness
# of a particular audit rule. The scheme is as follows:
# 
# -----------------------------------------------------------------------------------------
#  Tool used to load audit rules | Rule already defined  |  Audit rules file to inspect    |
# -----------------------------------------------------------------------------------------
#        auditctl                |     Doesn't matter    |  /etc/audit/audit.rules         |
# -----------------------------------------------------------------------------------------
#        augenrules              |          Yes          |  /etc/audit/rules.d/*.rules     |
#        augenrules              |          No           |  /etc/audit/rules.d/$key.rules  |
# -----------------------------------------------------------------------------------------
#
declare -a files_to_inspect

retval=0

# First check sanity of the specified audit tool
if [ "$tool" != 'auditctl' ] && [ "$tool" != 'augenrules' ]
then
	echo "Unknown audit rules loading tool: $1. Aborting."
	echo "Use either 'auditctl' or 'augenrules'!"
	return 1
# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
# file to the list of files to be inspected
elif [ "$tool" == 'auditctl' ]
then
	files_to_inspect+=('/etc/audit/audit.rules' )
# If audit tool is 'augenrules', then check if the audit rule is defined
# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
elif [ "$tool" == 'augenrules' ]
then
	# Extract audit $key from audit rule so we can use it later
	matches=()
	key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
	readarray -t matches < <(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
	if [ $? -ne 0 ]
	then
		retval=1
	fi
	for match in "${matches[@]}"
	do
		files_to_inspect+=("${match}")
	done
	# Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
	if [ ${#files_to_inspect[@]} -eq "0" ]
	then
		file_to_inspect="/etc/audit/rules.d/$key.rules"
		files_to_inspect=("$file_to_inspect")
		if [ ! -e "$file_to_inspect" ]
		then
			touch "$file_to_inspect"
			chmod 0640 "$file_to_inspect"
		fi
	fi
fi

#
# Indicator that we want to append $full_rule into $audit_file by default
local append_expected_rule=0

for audit_file in "${files_to_inspect[@]}"
do
	# Filter existing $audit_file rules' definitions to select those that:
	# * follow the rule pattern, and
	# * meet the hardware architecture requirement, and
	# * are current syscall group specific
	readarray -t existing_rules < <(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d"  "$audit_file")
	if [ $? -ne 0 ]
	then
		retval=1
	fi

	# Process rules found case-by-case
	for rule in "${existing_rules[@]}"
	do
		# Found rule is for same arch & key, but differs (e.g. in count of -S arguments)
		if [ "${rule}" != "${full_rule}" ]
		then
			# If so, isolate just '(-S \w)+' substring of that rule
			rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
			# Check if list of '-S syscall' arguments of that rule is subset
			# of '-S syscall' list of expected $full_rule
			if grep -q -- "$rule_syscalls" <<< "$full_rule"
			then
				# Rule is covered (i.e. the list of -S syscalls for this rule is
				# subset of -S syscalls of $full_rule => existing rule can be deleted
				# Thus delete the rule from audit.rules & our array
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi
				existing_rules=("${existing_rules[@]//$rule/}")
			else
				# Rule isn't covered by $full_rule - it besides -S syscall arguments
				# for this group contains also -S syscall arguments for other syscall
				# group. Example: '-S lchown -S fchmod -S fchownat' => group='chown'
				# since 'lchown' & 'fchownat' share 'chown' substring
				# Therefore:
				# * 1) delete the original rule from audit.rules
				# (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
				# * 2) delete the -S syscall arguments for this syscall group, but
				# keep those not belonging to this syscall group
				# (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
				# * 3) append the modified (filtered) rule again into audit.rules
				# if the same rule not already present
				#
				# 1) Delete the original rule
				sed -i -e "\;${rule};d" "$audit_file"
				if [ $? -ne 0 ]
				then
					retval=1
				fi

				# 2) Delete syscalls for this group, but keep those from other groups
				# Convert current rule syscall's string into array splitting by '-S' delimiter
				IFS_BKP="$IFS"
				IFS=$'-S'
				read -a rule_syscalls_as_array <<< "$rule_syscalls"
				# Reset IFS back to default
				IFS="$IFS_BKP"
				# Splitting by "-S" can't be replaced by the readarray functionality easily

				# Declare new empty string to hold '-S syscall' arguments from other groups
				new_syscalls_for_rule=''
				# Walk through existing '-S syscall' arguments
				for syscall_arg in "${rule_syscalls_as_array[@]}"
				do
					# Skip empty $syscall_arg values
					if [ "$syscall_arg" == '' ]
					then
						continue
					fi
					# If the '-S syscall' doesn't belong to current group add it to the new list
					# (together with adding '-S' delimiter back for each of such item found)
					if grep -q -v -- "$group" <<< "$syscall_arg"
					then
						new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
					fi
				done
				# Replace original '-S syscall' list with the new one for this rule
				updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
				# Squeeze repeated whitespace characters in rule definition (if any) into one
				updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
				# 3) Append the modified / filtered rule again into audit.rules
				#    (but only in case it's not present yet to prevent duplicate definitions)
				if ! grep -q -- "$updated_rule" "$audit_file"
				then
					echo "$updated_rule" >> "$audit_file"
				fi
			fi
		else
			# $audit_file already contains the expected rule form for this
			# architecture & key => don't insert it second time
			append_expected_rule=1
		fi
	done

	# We deleted all rules that were subset of the expected one for this arch & key.
	# Also isolated rules containing system calls not from this system calls group.
	# Now append the expected rule if it's not present in $audit_file yet
	if [[ ${append_expected_rule} -eq "0" ]]
	then
		echo "$full_rule" >> "$audit_file"
	fi
done

return $retval

}
        fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
        fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi
Group   Record Attempts to Alter Logon and Logout Events   Group contains 2 rules
Group   Records Events that Modify Date and Time Information   Group contains 5 rules
[ref]   Arbitrary changes to the system time can be used to obfuscate nefarious activities in log files, as well as to confuse network services that are highly dependent upon an accurate system time. All changes to the system time should be audited.

Rule   Record attempts to alter time through adjtimex   [ref]

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following line to a file with suffix .rules in the directory /etc/audit/rules.d:
-a always,exit -F arch=b32 -S adjtimex -F key=audit_time_rules
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S adjtimex -F key=audit_time_rules
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following line to /etc/audit/audit.rules file:
-a always,exit -F arch=b32 -S adjtimex -F key=audit_time_rules
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S adjtimex -F key=audit_time_rules
The -k option allows for the specification of a key in string form that can be used for better reporting capability through ausearch and aureport. Multiple system calls can be defined on the same line to save space if desired, but is not required. See an example of multiple combined syscalls:
-a always,exit -F arch=b64 -S adjtimex,settimeofday -F key=audit_time_rules
Rationale:
Arbitrary changes to the system time can be used to obfuscate nefarious activities in log files, as well as to confuse network services that are highly dependent upon an accurate system time (such as sshd). All changes to the system time should be audited.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_audit_rules_time_adjtimex
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.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, 3.1.7, CCI-001487, CCI-000169, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.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, SR 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, A.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, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.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, Req-10.4.2.b


Complexity:low
Disruption:low
Strategy:restrict
- name: Set architecture for audit tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_adjtimex
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

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

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - adjtimex

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b32_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b32_rules_d="{{ audit_syscalls_found_b32_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key audit_time_rules
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)audit_time_rules$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/audit_time_rules.rules as the recipient for the
        rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/audit_time_rules.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - adjtimex

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b32_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b32_audit_rules="{{ audit_syscalls_found_b32_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_audit_rules < audit_syscalls_number_of_syscalls
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_adjtimex
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

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

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - adjtimex

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b64 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b64_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b64 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b64_rules_d="{{ audit_syscalls_found_b64_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key audit_time_rules
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)audit_time_rules$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/audit_time_rules.rules as the recipient for the
        rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/audit_time_rules.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b64"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b64_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b64_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - adjtimex

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b64 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b64_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b64 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b64_audit_rules="{{ audit_syscalls_found_b64_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b64"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b64_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b64_audit_rules < audit_syscalls_number_of_syscalls
  when:
    - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
    - audit_arch == "b64"
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_adjtimex
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Rule   Record Attempts to Alter Time Through clock_settime   [ref]

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following line to a file with suffix .rules in the directory /etc/audit/rules.d:
-a always,exit -F arch=b32 -S clock_settime -F a0=0x0 -F key=time-change
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S clock_settime -F a0=0x0 -F key=time-change
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following line to /etc/audit/audit.rules file:
-a always,exit -F arch=b32 -S clock_settime -F a0=0x0 -F key=time-change
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S clock_settime -F a0=0x0 -F key=time-change
The -k option allows for the specification of a key in string form that can be used for better reporting capability through ausearch and aureport. Multiple system calls can be defined on the same line to save space if desired, but is not required. See an example of multiple combined syscalls:
-a always,exit -F arch=b64 -S adjtimex,settimeofday -F key=audit_time_rules
Rationale:
Arbitrary changes to the system time can be used to obfuscate nefarious activities in log files, as well as to confuse network services that are highly dependent upon an accurate system time (such as sshd). All changes to the system time should be audited.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_audit_rules_time_clock_settime
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.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, 3.1.7, CCI-001487, CCI-000169, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.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, SR 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, A.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, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.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, Req-10.4.2.b


Complexity:low
Disruption:low
Strategy:restrict
- name: Set architecture for audit tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_clock_settime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

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

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - clock_settime

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(?:-F[\s]+a0=0x0[\s]+)(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b32_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b32_rules_d="{{ audit_syscalls_found_b32_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key time-change
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)time-change$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/time-change.rules as the recipient for the rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/time-change.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -F a0=0x0 -k time-change' }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - clock_settime

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(?:-F[\s]+a0=0x0[\s]+)(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b32_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b32_audit_rules="{{ audit_syscalls_found_b32_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -F a0=0x0 -k time-change' }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_audit_rules < audit_syscalls_number_of_syscalls
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_clock_settime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

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

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - clock_settime

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b64 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(?:-F[\s]+a0=0x0[\s]+)(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b64_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b64 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b64_rules_d="{{ audit_syscalls_found_b64_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key time-change
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)time-change$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/time-change.rules as the recipient for the rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/time-change.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b64"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b64_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -F a0=0x0 -k time-change' }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b64_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - clock_settime

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b64 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(?:-F[\s]+a0=0x0[\s]+)(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b64_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b64 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b64_audit_rules="{{ audit_syscalls_found_b64_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b64"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b64_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -F a0=0x0 -k time-change' }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b64_audit_rules < audit_syscalls_number_of_syscalls
  when:
    - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
    - audit_arch == "b64"
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_clock_settime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Rule   Record attempts to alter time through settimeofday   [ref]

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following line to a file with suffix .rules in the directory /etc/audit/rules.d:
-a always,exit -F arch=b32 -S settimeofday -F key=audit_time_rules
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S settimeofday -F key=audit_time_rules
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following line to /etc/audit/audit.rules file:
-a always,exit -F arch=b32 -S settimeofday -F key=audit_time_rules
If the system is 64 bit then also add the following line:
-a always,exit -F arch=b64 -S settimeofday -F key=audit_time_rules
The -k option allows for the specification of a key in string form that can be used for better reporting capability through ausearch and aureport. Multiple system calls can be defined on the same line to save space if desired, but is not required. See an example of multiple combined syscalls:
-a always,exit -F arch=b64 -S adjtimex,settimeofday -F key=audit_time_rules
Rationale:
Arbitrary changes to the system time can be used to obfuscate nefarious activities in log files, as well as to confuse network services that are highly dependent upon an accurate system time (such as sshd). All changes to the system time should be audited.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_audit_rules_time_settimeofday
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.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, 3.1.7, CCI-001487, CCI-000169, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.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, SR 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, A.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, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.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, Req-10.4.2.b


Complexity:low
Disruption:low
Strategy:restrict
- name: Set architecture for audit tasks
  set_fact:
    audit_arch: b{{ ansible_architecture | regex_replace('.*(\d\d$)','\1') }}
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_settimeofday
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

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

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - settimeofday

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b32_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b32_rules_d="{{ audit_syscalls_found_b32_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key audit_time_rules
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)audit_time_rules$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/audit_time_rules.rules as the recipient for the
        rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/audit_time_rules.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - settimeofday

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b32_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b32_audit_rules="{{ audit_syscalls_found_b32_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_audit_rules < audit_syscalls_number_of_syscalls
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_settimeofday
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

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

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - settimeofday

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b64 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b64_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b64 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b64_rules_d="{{ audit_syscalls_found_b64_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key audit_time_rules
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)audit_time_rules$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/audit_time_rules.rules as the recipient for the
        rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/audit_time_rules.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b64"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b64_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b64_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - settimeofday

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b64 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b64[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b64_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b64 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b64_audit_rules="{{ audit_syscalls_found_b64_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b64"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b64_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b64_audit_rules < audit_syscalls_number_of_syscalls
  when:
    - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
    - audit_arch == "b64"
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_settimeofday
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Rule   Record Attempts to Alter Time Through stime   [ref]

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following line to a file with suffix .rules in the directory /etc/audit/rules.d for both 32 bit and 64 bit systems:
-a always,exit -F arch=b32 -S stime -F key=audit_time_rules
Since the 64 bit version of the "stime" system call is not defined in the audit lookup table, the corresponding "-F arch=b64" form of this rule is not expected to be defined on 64 bit systems (the aforementioned "-F arch=b32" stime rule form itself is sufficient for both 32 bit and 64 bit systems). If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following line to /etc/audit/audit.rules file for both 32 bit and 64 bit systems:
-a always,exit -F arch=b32 -S stime -F key=audit_time_rules
Since the 64 bit version of the "stime" system call is not defined in the audit lookup table, the corresponding "-F arch=b64" form of this rule is not expected to be defined on 64 bit systems (the aforementioned "-F arch=b32" stime rule form itself is sufficient for both 32 bit and 64 bit systems). The -k option allows for the specification of a key in string form that can be used for better reporting capability through ausearch and aureport. Multiple system calls can be defined on the same line to save space if desired, but is not required. See an example of multiple combined system calls:
-a always,exit -F arch=b64 -S adjtimex,settimeofday -F key=audit_time_rules
Rationale:
Arbitrary changes to the system time can be used to obfuscate nefarious activities in log files, as well as to confuse network services that are highly dependent upon an accurate system time (such as sshd). All changes to the system time should be audited.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_audit_rules_time_stime
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.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, 3.1.7, CCI-001487, CCI-000169, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.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, SR 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, A.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, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.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, Req-10.4.2.b


Complexity:low
Disruption:low
Strategy:restrict
- name: Perform remediation of Audit rules for stime syscall for x86 platform
  block:

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - stime

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/rules.d/
      find:
        paths: /etc/audit/rules.d
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: '*.rules'
      register: audit_syscalls_found_b32_rules_d
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/rules.d/
      set_fact: audit_syscalls_matched_b32_rules_d="{{ audit_syscalls_found_b32_rules_d.results|sum(attribute='matched')|int
        }}"

    - name: Search /etc/audit/rules.d for other rules with the key audit_time_rules
      find:
        paths: /etc/audit/rules.d
        contains: ^.*(?:-F key=|-k\s+)audit_time_rules$
        patterns: '*.rules'
      register: find_syscalls_files

    - name: Use /etc/audit/rules.d/audit_time_rules.rules as the recipient for the
        rule
      set_fact:
        all_files:
          - /etc/audit/rules.d/audit_time_rules.rules
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        == 0

    - name: Use matched file as the recipient for the rule
      set_fact:
        all_files:
          - '{{ find_syscalls_files.files | map(attribute=''path'') | list | first
            }}'
      when: find_syscalls_files.matched is defined and find_syscalls_files.matched
        > 0

    - name: Insert the syscall rule in {{ all_files[0] }}
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_rules_d.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in {{ all_files[0] }}
          lineinfile:
            path: '{{ all_files[0] }}'
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_rules_d < audit_syscalls_number_of_syscalls

    - name: Declare list of syscals
      set_fact:
        syscalls:
          - stime

    - name: Declare number of syscalls
      set_fact: audit_syscalls_number_of_syscalls="{{ syscalls|length|int }}"

    - name: Check existence of syscalls for architecture b32 in /etc/audit/audit.rules
      find:
        paths: /etc/audit
        contains: ^[\s]*-a[\s]+always,exit[\s]+(?:.*-F[\s]+arch=b32[\s]+)(?:.*(-S[\s]+{{
          item }}[\s]+|([\s]+|[,]){{ item }}([\s]+|[,]))).*(-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
        patterns: audit.rules
      register: audit_syscalls_found_b32_audit_rules
      loop: '{{ syscalls }}'

    - name: Get number of matched syscalls for architecture b32 in /etc/audit/audit.rules
      set_fact: audit_syscalls_matched_b32_audit_rules="{{ audit_syscalls_found_b32_audit_rules.results|sum(attribute='matched')|int
        }}"

    - name: Insert the syscall rule in /etc/audit/audit.rules
      block:

        - name: 'Construct rule: add rule list, action and arch'
          set_fact: tmpline="-a always,exit -F arch=b32"

        - name: 'Construct rule: add syscalls'
          set_fact: tmpline="{{ tmpline + ' -S ' + item.item }}"
          loop: '{{ audit_syscalls_found_b32_audit_rules.results }}'
          when: item.matched is defined and item.matched == 0

        - name: 'Construct rule: add fields and key'
          set_fact: tmpline="{{ tmpline + ' -k audit_time_rules' }}"

        - name: Insert the line in /etc/audit/audit.rules
          lineinfile:
            path: /etc/audit/audit.rules
            line: '{{ tmpline }}'
            create: true
            state: present
      when: audit_syscalls_matched_b32_audit_rules < audit_syscalls_number_of_syscalls
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_stime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Rule   Record Attempts to Alter the localtime File   [ref]

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following line to a file with suffix .rules in the directory /etc/audit/rules.d:
-w /etc/localtime -p wa -k audit_time_rules
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following line to /etc/audit/audit.rules file:
-w /etc/localtime -p wa -k audit_time_rules
The -k option allows for the specification of a key in string form that can be used for better reporting capability through ausearch and aureport and should always be used.
Rationale:
Arbitrary changes to the system time can be used to obfuscate nefarious activities in log files, as well as to confuse network services that are highly dependent upon an accurate system time (such as sshd). All changes to the system time should be audited.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_audit_rules_time_watch_localtime
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.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, 3.1.7, CCI-001487, CCI-000169, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.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, SR 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, A.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, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.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, Req-10.4.2.b


Complexity:low
Disruption:low
Strategy:restrict
- name: Check if watch rule for /etc/localtime already exists in /etc/audit/rules.d/
  find:
    paths: /etc/audit/rules.d
    contains: ^\s*-w\s+/etc/localtime\s+-p\s+wa(\s|$)+
    patterns: '*.rules'
  register: find_existing_watch_rules_d
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_watch_localtime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Search /etc/audit/rules.d for other rules with specified key audit_time_rules
  find:
    paths: /etc/audit/rules.d
    contains: ^.*(?:-F key=|-k\s+)audit_time_rules$
    patterns: '*.rules'
  register: find_watch_key
  when:
    - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_watch_localtime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Use /etc/audit/rules.d/audit_time_rules.rules as the recipient for the rule
  set_fact:
    all_files:
      - /etc/audit/rules.d/audit_time_rules.rules
  when:
    - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_watch_localtime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Use matched file as the recipient for the rule
  set_fact:
    all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
  when:
    - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_watch_localtime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Add watch rule for /etc/localtime in /etc/audit/rules.d/
  lineinfile:
    path: '{{ all_files[0] }}'
    line: -w /etc/localtime -p wa -k audit_time_rules
    create: true
    mode: '0640'
  when:
    - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_watch_localtime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Check if watch rule for /etc/localtime already exists in /etc/audit/audit.rules
  find:
    paths: /etc/audit/
    contains: ^\s*-w\s+/etc/localtime\s+-p\s+wa(\s|$)+
    patterns: audit.rules
  register: find_existing_watch_audit_rules
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_watch_localtime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Add watch rule for /etc/localtime in /etc/audit/audit.rules
  lineinfile:
    line: -w /etc/localtime -p wa -k audit_time_rules
    state: present
    dest: /etc/audit/audit.rules
    create: true
    mode: '0640'
  when:
    - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.2.b
    - audit_rules_time_watch_localtime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Rule   Make the auditd Configuration Immutable   [ref]

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following line to a file with suffix .rules in the directory /etc/audit/rules.d in order to make the auditd configuration immutable:
-e 2
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following line to /etc/audit/audit.rules file in order to make the auditd configuration immutable:
-e 2
With this setting, a reboot will be required to change any audit rules.
Rationale:
Making the audit configuration immutable prevents accidental as well as malicious modification of the audit rules, although it may be problematic if legitimate changes are needed during system operation
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_audit_rules_immutable
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 18, 19, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO01.06, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, BAI03.05, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, DSS06.02, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.3.1, 3.4.3, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.310(a)(2)(iv), 164.312(d), 164.310(d)(2)(iii), 164.312(b), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.7.3, 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, SR 2.1, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 5.2, SR 6.1, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, 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.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, 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, AC-6(9), CM-6(a), DE.AE-3, DE.AE-5, ID.SC-4, PR.AC-4, PR.DS-5, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.5.2, 4.1.17


Complexity:low
Disruption:low
Reboot:true
Strategy:restrict
- name: Collect all files from /etc/audit/rules.d with .rules extension
  find:
    paths: /etc/audit/rules.d/
    patterns: '*.rules'
  register: find_rules_d
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.3.1
    - NIST-800-171-3.4.3
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.2
    - audit_rules_immutable
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

- name: Remove the -e option from all Audit config files
  lineinfile:
    path: '{{ item }}'
    regexp: ^\s*(?:-e)\s+.*$
    state: absent
  loop: '{{ find_rules_d.files | map(attribute=''path'') | list + [''/etc/audit/audit.rules'']
    }}'
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.3.1
    - NIST-800-171-3.4.3
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.2
    - audit_rules_immutable
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

- name: Add Audit -e option into /etc/audit/rules.d/immutable.rules and /etc/audit/audit.rules
  lineinfile:
    path: '{{ item }}'
    create: true
    line: -e 2
  loop:
    - /etc/audit/audit.rules
    - /etc/audit/rules.d/immutable.rules
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CJIS-5.4.1.1
    - NIST-800-171-3.3.1
    - NIST-800-171-3.4.3
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.2
    - audit_rules_immutable
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

Rule   Record Events that Modify the System's Mandatory Access Controls   [ref]

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following line to a file with suffix .rules in the directory /etc/audit/rules.d:
-w /etc/selinux/ -p wa -k MAC-policy
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following line to /etc/audit/audit.rules file:
-w /etc/selinux/ -p wa -k MAC-policy
Rationale:
The system's mandatory access policy (SELinux) should not be arbitrarily changed by anything other than administrator action. All changes to MAC policy should be audited.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_audit_rules_mac_modification
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.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, 3.1.8, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.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, SR 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, A.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, AU-2(d), AU-12(c), CM-6(a), DE.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, FAU_GEN.1.1.c, Req-10.5.5

Rule   Record Events that Modify the System's Network Environment   [ref]

If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d, setting ARCH to either b32 or b64 as appropriate for your system:
-a always,exit -F arch=ARCH -S sethostname,setdomainname -F key=audit_rules_networkconfig_modification
-w /etc/issue -p wa -k audit_rules_networkconfig_modification
-w /etc/issue.net -p wa -k audit_rules_networkconfig_modification
-w /etc/hosts -p wa -k audit_rules_networkconfig_modification
-w /etc/sysconfig/network -p wa -k audit_rules_networkconfig_modification
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file, setting ARCH to either b32 or b64 as appropriate for your system:
-a always,exit -F arch=ARCH -S sethostname,setdomainname -F key=audit_rules_networkconfig_modification
-w /etc/issue -p wa -k audit_rules_networkconfig_modification
-w /etc/issue.net -p wa -k audit_rules_networkconfig_modification
-w /etc/hosts -p wa -k audit_rules_networkconfig_modification
-w /etc/sysconfig/network -p wa -k audit_rules_networkconfig_modification
Rationale:
The network environment should not be modified by anything other than administrator action. Any change to network parameters should be audited.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_audit_rules_networkconfig_modification
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.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, 3.1.7, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.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, SR 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, A.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, AU-2(d), AU-12(c), AC-6(9), CM-6(a), DE.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, Req-10.5.5

Rule   Record Attempts to Alter Process and Session Initiation Information   [ref]

The audit system already collects process information for all users and root. If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following lines to a file with suffix .rules in the directory /etc/audit/rules.d in order to watch for attempted manual edits of files involved in storing such process information:
-w /var/run/utmp -p wa -k session
-w /var/log/btmp -p wa -k session
-w /var/log/wtmp -p wa -k session
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following lines to /etc/audit/audit.rules file in order to watch for attempted manual edits of files involved in storing such process information:
-w /var/run/utmp -p wa -k session
-w /var/log/btmp -p wa -k session
-w /var/log/wtmp -p wa -k session
Rationale:
Manual editing of these files may indicate nefarious activity, such as an attacker attempting to remove evidence of an intrusion.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_audit_rules_session_events
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.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, 3.1.7, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.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, SR 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, 0582, 0584, 05885, 0586, 0846, 0957, A.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, AU-2(d), AU-12(c), CM-6(a), DE.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, FAU_GEN.1.1.c, Req-10.2.3

Rule   Ensure auditd Collects System Administrator Actions   [ref]

At a minimum, the audit system should collect administrator actions for all users and root. If the auditd daemon is configured to use the augenrules program to read audit rules during daemon startup (the default), add the following line to a file with suffix .rules in the directory /etc/audit/rules.d:
-w /etc/sudoers -p wa -k actions
-w /etc/sudoers.d/ -p wa -k actions
If the auditd daemon is configured to use the auditctl utility to read audit rules during daemon startup, add the following line to /etc/audit/audit.rules file:
-w /etc/sudoers -p wa -k actions
-w /etc/sudoers.d/ -p wa -k actions
Rationale:
The actions taken by system administrators should be audited to keep a record of what was executed on the system, as well as, for accountability purposes.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_audit_rules_sysadmin_actions
Identifiers and References

Identifiers:  CCE-85679-9

References:  1, 11, 12, 13, 14, 15, 16, 18, 19, 2, 3, 4, 5, 6, 7, 8, 9, 5.4.1.1, APO10.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, DSS06.03, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.1.7, CCI-000126, CCI-000130, CCI-000135, CCI-000169, CCI-000172, CCI-002884, 164.308(a)(1)(ii)(D), 164.308(a)(3)(ii)(A), 164.308(a)(5)(ii)(C), 164.312(a)(2)(i), 164.312(b), 164.312(d), 164.312(e), 4.2.3.10, 4.3.2.6.7, 4.3.3.2.2, 4.3.3.3.9, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.8, 4.3.3.6.6, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 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, SR 1.1, 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.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, A.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.1.2, A.6.2.1, A.6.2.2, 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, AU-3, AU-3.1, AU-12(a), AU-12.1(ii), AU-12.1(iv), MA-4(1)(a), DE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-1, PR.AC-3, PR.AC-4, PR.AC-6, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, FAU_GEN.1.1.c, Req-10.2.2, Req-10.2.5.b, SRG-OS-000037-GPOS-00015, SRG-OS-000042-GPOS-00020, SRG-OS-000392-GPOS-00172, SRG-OS-000462-GPOS-00206, SRG-OS-000471-GPOS-00215, SRG-OS-000462-VMM-001840, SRG-OS-000471-VMM-001910, SLES-15-030140, SV-234913r622137_rule


Complexity:low
Disruption:low
Strategy:restrict
- name: Search /etc/audit/rules.d for audit rule entries for sysadmin actions
  find:
    paths: /etc/audit/rules.d
    recurse: false
    contains: ^.*/etc/sudoers.*$
    patterns: '*.rules'
  register: find_audit_sysadmin_actions
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CCE-85679-9
    - CJIS-5.4.1.1
    - DISA-STIG-SLES-15-030140
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(a)
    - NIST-800-53-AU-12.1(ii)
    - NIST-800-53-AU-12.1(iv)
    - NIST-800-53-AU-3
    - NIST-800-53-AU-3.1
    - NIST-800-53-MA-4(1)(a)
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Use /etc/audit/rules.d/actions.rules as the recipient for the rule
  set_fact:
    all_sysadmin_actions_files:
      - /etc/audit/rules.d/actions.rules
  when:
    - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
    - find_audit_sysadmin_actions.matched is defined and find_audit_sysadmin_actions.matched
      == 0
  tags:
    - CCE-85679-9
    - CJIS-5.4.1.1
    - DISA-STIG-SLES-15-030140
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(a)
    - NIST-800-53-AU-12.1(ii)
    - NIST-800-53-AU-12.1(iv)
    - NIST-800-53-AU-3
    - NIST-800-53-AU-3.1
    - NIST-800-53-MA-4(1)(a)
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Use matched file as the recipient for the rule
  set_fact:
    all_sysadmin_actions_files:
      - '{{ find_audit_sysadmin_actions.files | map(attribute=''path'') | list | first
        }}'
  when:
    - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
    - find_audit_sysadmin_actions.matched is defined and find_audit_sysadmin_actions.matched
      > 0
  tags:
    - CCE-85679-9
    - CJIS-5.4.1.1
    - DISA-STIG-SLES-15-030140
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(a)
    - NIST-800-53-AU-12.1(ii)
    - NIST-800-53-AU-12.1(iv)
    - NIST-800-53-AU-3
    - NIST-800-53-AU-3.1
    - NIST-800-53-MA-4(1)(a)
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Inserts/replaces audit rule for /etc/sudoers rule in rules.d
  lineinfile:
    path: '{{ all_sysadmin_actions_files[0] }}'
    line: -w /etc/sudoers -p wa -k actions
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CCE-85679-9
    - CJIS-5.4.1.1
    - DISA-STIG-SLES-15-030140
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(a)
    - NIST-800-53-AU-12.1(ii)
    - NIST-800-53-AU-12.1(iv)
    - NIST-800-53-AU-3
    - NIST-800-53-AU-3.1
    - NIST-800-53-MA-4(1)(a)
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Inserts/replaces audit rule for /etc/sudoers.d rule in rules.d
  lineinfile:
    path: '{{ all_sysadmin_actions_files[0] }}'
    line: -w /etc/sudoers.d/ -p wa -k actions
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CCE-85679-9
    - CJIS-5.4.1.1
    - DISA-STIG-SLES-15-030140
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(a)
    - NIST-800-53-AU-12.1(ii)
    - NIST-800-53-AU-12.1(iv)
    - NIST-800-53-AU-3
    - NIST-800-53-AU-3.1
    - NIST-800-53-MA-4(1)(a)
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Inserts/replaces audit rule for /etc/sudoers in audit.rules
  lineinfile:
    path: /etc/audit/audit.rules
    line: -w /etc/sudoers -p wa -k actions
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CCE-85679-9
    - CJIS-5.4.1.1
    - DISA-STIG-SLES-15-030140
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(a)
    - NIST-800-53-AU-12.1(ii)
    - NIST-800-53-AU-12.1(iv)
    - NIST-800-53-AU-3
    - NIST-800-53-AU-3.1
    - NIST-800-53-MA-4(1)(a)
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

- name: Inserts/replaces audit rule for /etc/sudoers.d in audit.rules
  lineinfile:
    path: /etc/audit/audit.rules
    line: -w /etc/sudoers.d/ -p wa -k actions
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CCE-85679-9
    - CJIS-5.4.1.1
    - DISA-STIG-SLES-15-030140
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(a)
    - NIST-800-53-AU-12.1(ii)
    - NIST-800-53-AU-12.1(iv)
    - NIST-800-53-AU-3
    - NIST-800-53-AU-3.1
    - NIST-800-53-MA-4(1)(a)
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
Group   Configure auditd Data Retention   Group contains 5 rules
[ref]   The audit system writes data to /var/log/audit/audit.log. By default, auditd rotates 5 logs by size (6MB), retaining a maximum of 30MB of data in total, and refuses to write entries when the disk is too full. This minimizes the risk of audit data filling its partition and impacting other services. This also minimizes the risk of the audit daemon temporarily disabling the system if it cannot write audit log (which it can be configured to do). For a busy system or a system which is thoroughly auditing system activity, the default settings for data retention may be insufficient. The log file size needed will depend heavily on what types of events are being audited. First configure auditing to log all the events of interest. Then monitor the log size manually for awhile to determine what file size will allow you to keep the required data for the correct time period.

Using a dedicated partition for /var/log/audit prevents the auditd logs from disrupting system functionality if they fill, and, more importantly, prevents other activity in /var from filling the partition and stopping the audit trail. (The audit logs are size-limited and therefore unlikely to grow without bound unless configured to do so.) Some machines may have requirements that no actions occur which cannot be audited. If this is the case, then auditd can be configured to halt the machine if it runs out of space. Note: Since older logs are rotated, configuring auditd this way does not prevent older logs from being rotated away before they can be viewed. If your system is configured to halt when logging cannot be performed, make sure this can never happen under normal circumstances! Ensure that /var/log/audit is on its own partition, and that this partition is larger than the maximum amount of data auditd will retain normally.

Rule   Configure auditd mail_acct Action on Low Disk Space   [ref]

The auditd service can be configured to send email to a designated account in certain situations. Add or correct the following line in /etc/audit/auditd.conf to ensure that administrators are notified via email for those situations:
action_mail_acct = root
Rationale:
Email sent to the root account is typically aliased to the administrators of the system, who can take appropriate action.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_auditd_data_retention_action_mail_acct
Identifiers and References

Identifiers:  CCE-85604-7

References:  1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO11.04, APO12.06, APO13.01, BAI03.05, BAI04.04, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, MEA02.01, 3.3.1, CCI-000139, CCI-001855, 164.312(a)(2)(ii), 4.2.3.10, 4.3.3.3.9, 4.3.3.5.8, 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, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 7.1, SR 7.2, A.12.1.3, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.16.1.4, A.16.1.5, A.16.1.7, A.17.2.1, CIP-003-3 R1.3, CIP-003-3 R3, CIP-003-3 R3.1, CIP-003-3 R3.2, CIP-003-3 R3.3, CIP-003-3 R5.1.1, CIP-003-3 R5.3, CIP-004-3 R2.2.3, CIP-004-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.2, CIP-007-3 R5.2, CIP-007-3 R5.3.1, CIP-007-3 R5.3.2, CIP-007-3 R5.3.3, IA-5(1), AU-5(a), AU-5(2), CM-6(a), DE.AE-3, DE.AE-5, PR.DS-4, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.7.a, SRG-OS-000046-GPOS-00022, SRG-OS-000343-GPOS-00134, SRG-OS-000046-VMM-000210, SRG-OS-000343-VMM-001240, SLES-15-030570, SV-234956r622137_rule


# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; then


var_auditd_action_mail_acct="root"



AUDITCONFIG=/etc/audit/auditd.conf
# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="${cce}"
  else
    cce="CCE"
  fi

  # 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' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # 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 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}
replace_or_append $AUDITCONFIG '^action_mail_acct' "$var_auditd_action_mail_acct" "CCE-85604-7"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Strategy:restrict
- name: XCCDF Value var_auditd_action_mail_acct # promote to variable
  set_fact:
    var_auditd_action_mail_acct: !!str root
  tags:
    - always

- name: Configure auditd mail_acct Action on Low Disk Space
  lineinfile:
    dest: /etc/audit/auditd.conf
    line: action_mail_acct = {{ var_auditd_action_mail_acct }}
    state: present
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CCE-85604-7
    - CJIS-5.4.1.1
    - DISA-STIG-SLES-15-030570
    - NIST-800-171-3.3.1
    - NIST-800-53-AU-5(2)
    - NIST-800-53-AU-5(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)
    - PCI-DSS-Req-10.7.a
    - auditd_data_retention_action_mail_acct
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Rule   Configure auditd admin_space_left Action on Low Disk Space   [ref]

The auditd service can be configured to take an action when disk space is running low but prior to running out of space completely. Edit the file /etc/audit/auditd.conf. Add or modify the following line, substituting ACTION appropriately:
admin_space_left_action = ACTION
Set this value to single to cause the system to switch to single user mode for corrective action. Acceptable values also include suspend and halt. For certain systems, the need for availability outweighs the need to log all actions, and a different setting should be determined. Details regarding all possible values for ACTION are described in the auditd.conf man page.
Rationale:
Administrators should be made aware of an inability to record audit records. If a separate partition or logical volume of adequate size is used, running low on space for audit records should never occur.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_auditd_data_retention_admin_space_left_action
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO11.04, APO12.06, APO13.01, BAI03.05, BAI04.04, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, MEA02.01, 3.3.1, CCI-000140, CCI-001343, CCI-001855, 164.312(a)(2)(ii), 4.2.3.10, 4.3.3.3.9, 4.3.3.5.8, 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, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 7.1, SR 7.2, A.12.1.3, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.16.1.4, A.16.1.5, A.16.1.7, A.17.2.1, AU-5(b), AU-5(2), AU-5(1), AU-5(4), CM-6(a), DE.AE-3, DE.AE-5, PR.DS-4, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.7, SRG-OS-000343-GPOS-00134

Rule   Configure auditd Max Log File Size   [ref]

Determine the amount of audit data (in megabytes) which should be retained in each log file. Edit the file /etc/audit/auditd.conf. Add or modify the following line, substituting the correct value of 6 for STOREMB:
max_log_file = STOREMB
Set the value to 6 (MB) or higher for general-purpose systems. Larger values, of course, support retention of even more audit data.
Rationale:
The total storage for audit log files must be large enough to retain log information over the period required. This is a function of the maximum log file size and the number of logs retained.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_auditd_data_retention_max_log_file
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 19, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO11.04, APO12.06, BAI03.05, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, MEA02.01, 4.2.3.10, 4.3.3.3.9, 4.3.3.5.8, 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, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.16.1.4, A.16.1.5, A.16.1.7, CIP-004-3 R2.2.3, CIP-004-3 R3.3, CIP-007-3 R5.2, CIP-007-3 R5.3.1, CIP-007-3 R5.3.2, CIP-007-3 R5.3.3, CIP-007-3 R6.5, AU-11, CM-6(a), DE.AE-3, DE.AE-5, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.7

Rule   Configure auditd max_log_file_action Upon Reaching Maximum Log Size   [ref]

The default action to take when the logs reach their maximum size is to rotate the log files, discarding the oldest one. To configure the action taken by auditd, add or correct the line in /etc/audit/auditd.conf:
max_log_file_action = ACTION
Possible values for ACTION are described in the auditd.conf man page. These include:
  • syslog
  • suspend
  • rotate
  • keep_logs
Set the ACTION to rotate to ensure log rotation occurs. This is the default. The setting is case-insensitive.
Rationale:
Automatically rotating logs (by setting this to rotate) minimizes the chances of the system unexpectedly running out of disk space by being overwhelmed with log data. However, for systems that must never discard log data, or which use external processes to transfer it and reclaim space, keep_logs can be employed.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_auditd_data_retention_max_log_file_action
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO11.04, APO12.06, APO13.01, BAI03.05, BAI04.04, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, MEA02.01, CCI-000140, 164.312(a)(2)(ii), 4.2.3.10, 4.3.3.3.9, 4.3.3.5.8, 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, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 7.1, SR 7.2, A.12.1.3, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.16.1.4, A.16.1.5, A.16.1.7, A.17.2.1, AU-5(b), AU-5(2), AU-5(1), AU-5(4), CM-6(a), DE.AE-3, DE.AE-5, PR.DS-4, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.7, SRG-OS-000047-GPOS-00023

Rule   Configure auditd space_left Action on Low Disk Space   [ref]

The auditd service can be configured to take an action when disk space starts to run low. Edit the file /etc/audit/auditd.conf. Modify the following line, substituting ACTION appropriately:
space_left_action = ACTION
Possible values for ACTION are described in the auditd.conf man page. These include:
  • syslog
  • email
  • exec
  • suspend
  • single
  • halt
Set this to email (instead of the default, which is suspend) as it is more likely to get prompt attention. Acceptable values also include suspend, single, and halt.
Rationale:
Notifying administrators of an impending disk space problem may allow them to take corrective action prior to any disruption.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_auditd_data_retention_space_left_action
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO11.04, APO12.06, APO13.01, BAI03.05, BAI04.04, BAI08.02, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.04, DSS05.07, MEA02.01, 3.3.1, CCI-001855, 164.312(a)(2)(ii), 4.2.3.10, 4.3.3.3.9, 4.3.3.5.8, 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, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 7.1, SR 7.2, A.12.1.3, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.16.1.4, A.16.1.5, A.16.1.7, A.17.2.1, AU-5(b), AU-5(2), AU-5(1), AU-5(4), CM-6(a), DE.AE-3, DE.AE-5, PR.DS-4, PR.PT-1, RS.AN-1, RS.AN-4, Req-10.7, SRG-OS-000343-GPOS-00134, SRG-OS-000343-VMM-001240

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
Identifiers and References

Identifiers:  CCE-85612-0

References:  BP28(R50), CCI-000172, CCI-001814, CCI-001875, CCI-001877, CCI-001878, CCI-001879, CCI-001880, CCI-001881, CCI-001882, CCI-001889, CCI-001914, CCI-000169, CIP-004-3 R3.3, CIP-007-3 R6.5, AC-7(a), AU-7(1), AU-7(2), AU-14, AU-12(2), AU-2(a), CM-6(a), SRG-OS-000122-GPOS-00063, 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-000359-GPOS-00146, SRG-OS-000365-GPOS-00152, SRG-OS-000474-GPOS-00219, SRG-OS-000475-GPOS-00220, SRG-OS-000480-GPOS-00227, SRG-OS-000062-GPOS-00031, SLES-15-030650, SV-234964r622137_rule


Complexity:low
Disruption:low
Strategy:enable
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; then

zypper install -y "audit"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Strategy:enable
- name: Ensure audit is installed
  package:
    name: audit
    state: present
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CCE-85612-0
    - DISA-STIG-SLES-15-030650
    - 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)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_audit_installed

Complexity:low
Disruption:low
Strategy:enable
include install_audit

class install_audit {
  package { 'audit':
    ensure => 'installed',
  }
}


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

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
Identifiers and References

Identifiers:  CCE-85581-7

References:  5.4.1.1, 3.3.1, 3.3.2, 3.3.6, CCI-000126, CCI-000130, CCI-000131, CCI-000132, CCI-000133, CCI-000134, CCI-000135, CCI-000154, CCI-000158, CCI-000366, CCI-001464, CCI-001487, CCI-001814, CCI-001876, CCI-002884, CCI-000169, 164.308(a)(1)(ii)(D), 164.308(a)(5)(ii)(C), 164.310(a)(2)(iv), 164.310(d)(2)(iii), 164.312(b), AC-2(g), AU-3, AU-10, AU-2(d), AU-12(c), AU-14(1), AC-6(9), CM-6(a), CIP-004-3 R3.3, CIP-007-3 R6.5, DE.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, Req-10.1, 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-000365-GPOS-00152, SRG-OS-000392-GPOS-00172, SRG-OS-000480-GPOS-00227, SRG-OS-000062-GPOS-00031, SRG-OS-000037-VMM-000150, SRG-OS-000063-VMM-000310, SRG-OS-000038-VMM-000160, SRG-OS-000039-VMM-000170, SRG-OS-000040-VMM-000180, SRG-OS-000041-VMM-000190, SR 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, 4.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, APO10.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, A.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, 1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9, SLES-15-030050, SV-234904r622137_rule


Complexity:low
Disruption:low
Strategy:enable
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; then

SYSTEMCTL_EXEC='/usr/bin/systemctl'
"$SYSTEMCTL_EXEC" unmask 'auditd.service'
"$SYSTEMCTL_EXEC" start 'auditd.service'
"$SYSTEMCTL_EXEC" enable 'auditd.service'

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Strategy:enable
- name: Enable service auditd
  block:

    - name: Gather the package facts
      package_facts:
        manager: auto

    - name: Enable service auditd
      service:
        name: auditd
        enabled: 'yes'
        state: started
        masked: 'no'
      when:
        - '"audit" in ansible_facts.packages'
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CCE-85581-7
    - CJIS-5.4.1.1
    - DISA-STIG-SLES-15-030050
    - 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)
    - PCI-DSS-Req-10.1
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_auditd_enabled

Complexity:low
Disruption:low
Strategy:enable
include enable_auditd

class enable_auditd {
  service {'auditd':
    enable => true,
    ensure => 'running',
  }
}

Rule   Enable Auditing for Processes Which Start Prior to the Audit Daemon   [ref]

To ensure all processes can be audited, even those which start prior to the audit daemon, add the argument audit=1 to the default GRUB 2 command line for the Linux operating system in /boot/grub2/grubenv, in the manner below:
# grub2-editenv - set "$(grub2-editenv - list | grep kernelopts) audit=1"
Warning:  The GRUB 2 configuration file, grub.cfg, is automatically updated each time a new kernel is installed. Note that any changes to /etc/default/grub require rebuilding the grub.cfg file. To update the GRUB 2 configuration file manually, use the
grub2-mkconfig -o
command as follows:
  • On BIOS-based machines, issue the following command as root:
    ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
  • On UEFI-based machines, issue the following command as root:
    ~]# grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg
Rationale:
Each process on the system carries an "auditable" flag which indicates whether its activities can be audited. Although auditd takes care of enabling this for all processes which launch after it does, adding the kernel argument ensures it is set for every process during boot.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_grub2_audit_argument
Identifiers and References

References:  1, 11, 12, 13, 14, 15, 16, 19, 3, 4, 5, 6, 7, 8, 5.4.1.1, APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS05.02, DSS05.03, DSS05.04, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01, 3.3.1, CCI-001464, CCI-000130, CCI-000169, 164.308(a)(1)(ii)(D), 164.308(a)(5)(ii)(C), 164.310(a)(2)(iv), 164.310(d)(2)(iii), 164.312(b), 4.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, SR 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 7.1, SR 7.6, A.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.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, AC-17(1), AU-14(1), AU-10, CM-6(a), IR-5(1), DE.AE-3, DE.AE-5, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4, Req-10.3, SRG-OS-000254-GPOS-00095, SRG-OS-000062-GPOS-00031, SRG-OS-000254-VMM-000880

Rule   Extend Audit Backlog Limit for the Audit Daemon   [ref]

To improve the kernel capacity to queue all log events, even those which occurred prior to the audit daemon, add the argument audit_backlog_limit=8192 to the default GRUB 2 command line for the Linux operating system in /etc/default/grub, in the manner below:
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=VolGroup/LogVol06 rd.lvm.lv=VolGroup/lv_swap rhgb quiet rd.shell=0 audit=1 audit_backlog_limit=8192"
Warning:  The GRUB 2 configuration file, grub.cfg, is automatically updated each time a new kernel is installed. Note that any changes to /etc/default/grub require rebuilding the grub.cfg file. To update the GRUB 2 configuration file manually, use the
grub2-mkconfig -o
command as follows:
  • On BIOS-based machines, issue the following command as root:
    ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
  • On UEFI-based machines, issue the following command as root:
    ~]# grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg
Rationale:
audit_backlog_limit sets the queue length for audit events awaiting transfer to the audit daemon. Until the audit daemon is up and running, all log messages are stored in this queue. If the queue is overrun during boot process, the action defined by audit failure flag is taken.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_grub2_audit_backlog_limit_argument
Identifiers and References

References:  CCI-001849, CM-6(a), SRG-OS-000254-GPOS-00095, SRG-OS-000341-GPOS-00132

Group   GRUB2 bootloader configuration   Group contains 1 group and 4 rules
[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 SUSE Linux Enterprise 15 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.
Group   Non-UEFI GRUB2 bootloader configuration   Group contains 4 rules
[ref]   Non-UEFI GRUB2 bootloader configuration

Rule   Verify /boot/grub2/grub.cfg Group Ownership   [ref]

The file /boot/grub2/grub.cfg should be group-owned by the root group to prevent destruction or modification of the file. To properly set the group owner of {{{ grub2_boot_path }}}/grub.cfg, run the command:
$ sudo chgrp root {{{ grub2_boot_path }}}/grub.cfg
Rationale:
The root group is a highly-privileged group. Furthermore, the group-owner of this file should not have any access privileges anyway.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_groupowner_grub2_cfg
Identifiers and References

References:  12, 13, 14, 15, 16, 18, 3, 5, 5.5.2.2, APO01.06, DSS05.04, DSS05.07, DSS06.02, 3.4.5, CCI-000225, 164.308(a)(1)(ii)(B), 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.310(a)(1), 164.310(a)(2)(i), 164.310(a)(2)(ii), 164.310(a)(2)(iii), 164.310(b), 164.310(c), 164.310(d)(1), 164.310(d)(2)(iii), 4.3.3.7.3, SR 2.1, SR 5.2, A.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, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-7.1


Complexity:low
Disruption:low
Strategy:configure
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; then

chgrp 0 /boot/grub2/grub.cfg

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /boot/grub2/grub.cfg
  stat:
    path: /boot/grub2/grub.cfg
  register: file_exists
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CJIS-5.5.2.2
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-7.1
    - configure_strategy
    - file_groupowner_grub2_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

- name: Ensure group owner 0 on /boot/grub2/grub.cfg
  file:
    path: /boot/grub2/grub.cfg
    group: '0'
  when:
    - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
    - file_exists.stat is defined and file_exists.stat.exists
  tags:
    - CJIS-5.5.2.2
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-7.1
    - configure_strategy
    - file_groupowner_grub2_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

Rule   Verify /boot/grub2/grub.cfg User Ownership   [ref]

The file /boot/grub2/grub.cfg should be owned by the root user to prevent destruction or modification of the file. To properly set the owner of {{{ grub2_boot_path }}}/grub.cfg, run the command:
$ sudo chown root {{{ grub2_boot_path }}}/grub.cfg 
Rationale:
Only root should be able to modify important boot parameters.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_owner_grub2_cfg
Identifiers and References

References:  12, 13, 14, 15, 16, 18, 3, 5, 5.5.2.2, APO01.06, DSS05.04, DSS05.07, DSS06.02, 3.4.5, CCI-000225, 164.308(a)(1)(ii)(B), 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.310(a)(1), 164.310(a)(2)(i), 164.310(a)(2)(ii), 164.310(a)(2)(iii), 164.310(b), 164.310(c), 164.310(d)(1), 164.310(d)(2)(iii), 4.3.3.7.3, SR 2.1, SR 5.2, A.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, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-7.1


Complexity:low
Disruption:low
Strategy:configure
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; then

chown 0 /boot/grub2/grub.cfg

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /boot/grub2/grub.cfg
  stat:
    path: /boot/grub2/grub.cfg
  register: file_exists
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CJIS-5.5.2.2
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-7.1
    - configure_strategy
    - file_owner_grub2_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

- name: Ensure owner 0 on /boot/grub2/grub.cfg
  file:
    path: /boot/grub2/grub.cfg
    owner: '0'
  when:
    - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
    - file_exists.stat is defined and file_exists.stat.exists
  tags:
    - CJIS-5.5.2.2
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-7.1
    - configure_strategy
    - file_owner_grub2_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

Rule   Verify /boot/grub2/grub.cfg Permissions   [ref]

File permissions for /boot/grub2/grub.cfg should be set to 600. To properly set the permissions of {{{ grub2_boot_path }}}/grub.cfg, run the command:
$ sudo chmod 600 {{{ grub2_boot_path }}}/grub.cfg
Rationale:
Proper permissions ensure that only the root user can modify important boot parameters.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_grub2_cfg
Identifiers and References

References:  12, 13, 14, 15, 16, 18, 3, 5, APO01.06, DSS05.04, DSS05.07, DSS06.02, 3.4.5, CCI-000225, 164.308(a)(1)(ii)(B), 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.310(a)(1), 164.310(a)(2)(i), 164.310(a)(2)(ii), 164.310(a)(2)(iii), 164.310(b), 164.310(c), 164.310(d)(1), 164.310(d)(2)(iii), 4.3.3.7.3, SR 2.1, SR 5.2, A.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, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5


Complexity:low
Disruption:low
Strategy:configure
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; then

chmod 0600 /boot/grub2/grub.cfg

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /boot/grub2/grub.cfg
  stat:
    path: /boot/grub2/grub.cfg
  register: file_exists
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_grub2_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

- name: Ensure permission 0600 on /boot/grub2/grub.cfg
  file:
    path: /boot/grub2/grub.cfg
    mode: '0600'
  when:
    - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
    - file_exists.stat is defined and file_exists.stat.exists
  tags:
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_grub2_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

Rule   Set Boot Loader Password in grub2   [ref]

The grub2 boot loader should have a superuser account and password protection enabled to protect boot-time settings.

Since plaintext passwords are a security risk, generate a hash for the password by running the following command:
$ grub2-mkpasswd-pbkdf2
When prompted, enter the password that was selected.

Using the hash from the output, modify the /etc/grub.d/40_custom file with the following content:
set superusers="boot"
password_pbkdf2 boot grub.pbkdf2.sha512.VeryLongString
NOTE: the bootloader superuser account and password MUST differ from the root account and password.

Once the superuser password has been added, update the grub.cfg file by running:
grub2-mkconfig -o /boot/grub2/grub.cfg
Warning:  To prevent hard-coded passwords, automatic remediation of this control is not available. Remediation must be automated as a component of machine provisioning, or followed manually as outlined above. Also, do NOT manually add the superuser account and password to the grub.cfg file as the grub2-mkconfig command overwrites this file.
Rationale:
Password protection on the boot loader configuration ensures users with physical access cannot trivially alter important bootloader settings. These include which kernel to use, and whether to enter single-user mode.
Severity: 
high
Rule ID:xccdf_org.ssgproject.content_rule_grub2_password
Identifiers and References

Identifiers:  CCE-83274-1

References:  BP28(R17), 1, 11, 12, 14, 15, 16, 18, 3, 5, DSS05.02, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.06, DSS06.10, 3.4.5, CCI-000213, 164.308(a)(1)(ii)(B), 164.308(a)(7)(i), 164.308(a)(7)(ii)(A), 164.310(a)(1), 164.310(a)(2)(i), 164.310(a)(2)(ii), 164.310(a)(2)(iii), 164.310(b), 164.310(c), 164.310(d)(1), 164.310(d)(2)(iii), 4.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, SR 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, A.18.1.4, A.6.1.2, 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, CM-6(a), PR.AC-1, PR.AC-4, PR.AC-6, PR.AC-7, PR.PT-3, FIA_UAU.1, SRG-OS-000080-GPOS-00048, SLES-15-010190, SV-234819r622137_rule

Group   Configure Syslog   Group contains 2 groups and 6 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 SUSE Linux Enterprise 15, 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 SUSE Linux Enterprise 15 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 root. 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 root, run the following command to correct this:
$ sudo chgrp root 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
Identifiers and References

References:  BP28(R46), BP28(R5), 12, 13, 14, 15, 16, 18, 3, 5, APO01.06, DSS05.04, DSS05.07, DSS06.02, CCI-001314, 4.3.3.7.3, SR 2.1, SR 5.2, 0988, 1405, A.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, CIP-003-3 R5.1.1, CIP-003-3 R5.3, CIP-004-3 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, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-10.5.1, Req-10.5.2

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

The owner of all log files written by rsyslog should be root. 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 root, run the following command to correct this:
$ sudo chown root 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
Identifiers and References

References:  BP28(R46), BP28(R5), 12, 13, 14, 15, 16, 18, 3, 5, APO01.06, DSS05.04, DSS05.07, DSS06.02, CCI-001314, 4.3.3.7.3, SR 2.1, SR 5.2, 0988, 1405, A.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, CIP-003-3 R5.1.1, CIP-003-3 R5.3, CIP-004-3 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, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, Req-10.5.1, Req-10.5.2

Rule   Ensure System Log Files Have Correct Permissions   [ref]

The file permissions for all log files written by rsyslog should be set to 600, 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 600 or more restrictive, run the following command to correct this:
$ sudo chmod 0600 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
Identifiers and References

References:  BP28(R36), CCI-001314, 0988, 1405, CIP-003-3 R5.1.1, CIP-003-3 R5.3, CIP-004-3 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, CM-6(a), AC-6(1), Req-10.5.1, Req-10.5.2

Group   Rsyslog Logs Sent To Remote Host   Group contains 1 rule
[ref]   If system logs are to be useful in detecting malicious activities, it is necessary to send logs to a remote server. An intruder who has compromised the root account on a system may delete the log entries which indicate that the system was attacked before they are seen by an administrator.

However, it is recommended that logs be stored on the local host in addition to being sent to the loghost, especially if rsyslog has been configured to use the UDP protocol to send messages over a network. UDP does not guarantee reliable delivery, and moderately busy sites will lose log messages occasionally, especially in periods of high traffic which may be the result of an attack. In addition, remote rsyslog messages are not authenticated in any way by default, so it is easy for an attacker to introduce spurious messages to the central log server. Also, some problems cause loss of network connectivity, which will prevent the sending of messages to the central server. For all of these reasons, it is better to store log messages both centrally and on each host, so that they can be correlated if necessary.

Rule   Ensure Logs Sent To Remote Host   [ref]

To configure rsyslog to send logs to a remote log server, open /etc/rsyslog.conf and read and understand the last section of the file, which describes the multiple directives necessary to activate remote logging. Along with these other directives, the system can be configured to forward its logs to a particular log server by adding or correcting one of the following lines, substituting logcollector appropriately. The choice of protocol depends on the environment of the system; although TCP and RELP provide more reliable message delivery, they may not be supported in all environments.
To use UDP for log message delivery:
*.* @logcollector

To use TCP for log message delivery:
*.* @@logcollector

To use RELP for log message delivery:
*.* :omrelp:logcollector

There must be a resolvable DNS CNAME or Alias record set to "logcollector" for logs to be sent correctly to the centralized logging utility.
Rationale:
A log server (loghost) receives syslog messages from one or more systems. This data can be used as an additional log source in the event a system is compromised and its local logs are suspect. Forwarding log messages to a remote loghost also provides system administrators with a centralized place to view the status of multiple hosts within the enterprise.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_rsyslog_remote_loghost
Identifiers and References

Identifiers:  CCE-85552-8

References:  BP28(R7), NT28(R43), NT12(R5), 1, 13, 14, 15, 16, 2, 3, 5, 6, APO11.04, APO13.01, BAI03.05, BAI04.04, DSS05.04, DSS05.07, MEA02.01, CCI-000366, CCI-001348, CCI-000136, CCI-001851, 164.308(a)(1)(ii)(D), 164.308(a)(5)(ii)(B), 164.308(a)(5)(ii)(C), 164.308(a)(6)(ii), 164.308(a)(8), 164.310(d)(2)(iii), 164.312(b), 164.314(a)(2)(i)(C), 164.314(a)(2)(iii), 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, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 7.1, SR 7.2, 0988, 1405, A.12.1.3, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.17.2.1, CIP-003-3 R5.2, CIP-004-3 R3.3, CM-6(a), AU-4(1), AU-9(2), PR.DS-4, PR.PT-1, FAU_GEN.1.1.c, SRG-OS-000479-GPOS-00224, SRG-OS-000480-GPOS-00227, SRG-OS-000342-GPOS-00133, SRG-OS-000032-VMM-000130, SLES-15-010580, SV-234865r622137_rule


Complexity:low
Disruption:low
Strategy:restrict
- name: XCCDF Value rsyslog_remote_loghost_address # promote to variable
  set_fact:
    rsyslog_remote_loghost_address: !!str logcollector
  tags:
    - always

- name: Set rsyslog remote loghost
  lineinfile:
    dest: /etc/rsyslog.conf
    regexp: ^\*\.\*
    line: '*.* @@{{ rsyslog_remote_loghost_address }}'
    create: true
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  tags:
    - CCE-85552-8
    - DISA-STIG-SLES-15-010580
    - NIST-800-53-AU-4(1)
    - NIST-800-53-AU-9(2)
    - NIST-800-53-CM-6(a)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - rsyslog_remote_loghost

Rule   Ensure rsyslog is Installed   [ref]

Rsyslog is installed by default. The rsyslog package can be installed with the following command:
 $ sudo zypper 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
Identifiers and References

References:  BP28(R5), NT28(R46), 1, 14, 15, 16, 3, 5, 6, APO11.04, BAI03.05, DSS05.04, DSS05.07, MEA02.01, CCI-001311, CCI-001312, CCI-000366, 164.312(a)(2)(ii), 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, SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, CM-6(a), PR.PT-1, SRG-OS-000479-GPOS-00224, SRG-OS-000051-GPOS-00024, SRG-OS-000480-GPOS-00227


Complexity:low
Disruption:low
Strategy:enable
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; then

zypper install -y "rsyslog"

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Strategy:enable
- name: Ensure rsyslog is installed
  package:
    name: rsyslog
    state: present
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  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
Strategy:enable
include install_rsyslog

class install_rsyslog {
  package { 'rsyslog':
    ensure => 'installed',
  }
}


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

Rule   Enable rsyslog Service   [ref]

The rsyslog service provides syslog-style logging by default on SUSE Linux Enterprise 15. 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
Identifiers and References

References:  BP28(R5), NT28(R46), 1, 12, 13, 14, 15, 16, 2, 3, 5, 6, 7, 8, 9, APO10.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, CCI-001311, CCI-001312, CCI-001557, CCI-001851, CCI-000366, 164.312(a)(2)(ii), 4.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, SR 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, A.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, CM-6(a), AU-4(1), DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.DS-4, PR.PT-1, SRG-OS-000480-GPOS-00227


Complexity:low
Disruption:low
Strategy:enable
# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; then

SYSTEMCTL_EXEC='/usr/bin/systemctl'
"$SYSTEMCTL_EXEC" unmask 'rsyslog.service'
"$SYSTEMCTL_EXEC" start 'rsyslog.service'
"$SYSTEMCTL_EXEC" enable 'rsyslog.service'

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi

Complexity:low
Disruption:low
Strategy:enable
- name: Enable service rsyslog
  block:

    - name: Gather the package facts
      package_facts:
        manager: auto

    - name: Enable service rsyslog
      service:
        name: rsyslog
        enabled: 'yes'
        state: started
        masked: 'no'
      when:
        - '"rsyslog" in ansible_facts.packages'
  when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
  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
Strategy:enable
include enable_rsyslog

class enable_rsyslog {
  service {'rsyslog':
    enable => true,
    ensure => 'running',
  }
}
Group   Network Configuration and Firewalls   Group contains 15 groups and 30 rules
[ref]   Most systems must be connected to a network of some sort, and this brings with it the substantial risk of network attack. This section discusses the security impact of decisions about networking which must be made when configuring a system.

This section also discusses firewalls, network access controls, and other network security frameworks, which allow system-level rules to be written that can limit an attackers' ability to connect to your system. These rules can specify that network traffic should be allowed or denied from certain IP addresses, hosts, and networks. The rules can also specify which of the system's network services are available to particular hosts or networks.
Group   firewalld   Group contains 2 groups and 3 rules
[ref]   The dynamic firewall daemon firewalld provides a dynamically managed firewall with support for network “zones” to assign a level of trust to a network and its associated connections and interfaces. It has support for IPv4 and IPv6 firewall settings. It supports Ethernet bridges and has a separation of runtime and permanent configuration options. It also has an interface for services or applications to add firewall rules directly.
A graphical configuration tool, firewall-config, is used to configure firewalld, which in turn uses iptables tool to communicate with Netfilter in the kernel which implements packet filtering.
The firewall service provided by firewalld is dynamic rather than static because changes to the configuration can be made at anytime and are immediately implemented. There is no need to save or apply the changes. No unintended disruption of existing network connections occurs as no part of the firewall has to be reloaded.
Group   Inspect and Activate Default firewalld Rules   Group contains 2 rules
[ref]   Firewalls can be used to separate networks into different zones based on the level of trust the user has decided to place on the devices and traffic within that network. NetworkManager informs firewalld to which zone an interface belongs. An interface's assigned zone can be changed by NetworkManager or via the firewall-config tool.
The zone settings in /etc/firewalld/ are a range of preset settings which can be quickly applied to a network interface. These are the zones provided by firewalld sorted according to the default trust level of the zones from untrusted to trusted:
  • drop

    Any incoming network packets are dropped, there is no reply. Only outgoing network connections are possible.

  • block

    Any incoming network connections are rejected with an icmp-host-prohibited message for IPv4 and icmp6-adm-prohibited for IPv6. Only network connections initiated from within the system are possible.

  • public

    For use in public areas. You do not trust the other computers on the network to not harm your computer. Only selected incoming connections are accepted.

  • external

    For use on external networks with masquerading enabled especially for routers. You do not trust the other computers on the network to not harm your computer. Only selected incoming connections are accepted.

  • dmz

    For computers in your demilitarized zone that are publicly-accessible with limited access to your internal network. Only selected incoming connections are accepted.

  • work

    For use in work areas. You mostly trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.

  • home

    For use in home areas. You mostly trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.

  • internal

    For use on internal networks. You mostly trust the other computers on the networks to not harm your computer. Only selected incoming connections are accepted.

  • trusted

    All network connections are accepted.


It is possible to designate one of these zones to be the default zone. When interface connections are added to NetworkManager, they are assigned to the default zone. On installation, the default zone in firewalld is set to be the public zone.
To find out all the settings of a zone, for example the public zone, enter the following command as root:
# firewall-cmd --zone=public --list-all
Example output of this command might look like the following:
# firewall-cmd --zone=public --list-all
public
  interfaces:
  services: mdns dhcpv6-client ssh
  ports:
  forward-ports:
  icmp-blocks: source-quench
To view the network zones currently active, enter the following command as root:
# firewall-cmd --get-service
The following listing displays the result of this command on common SUSE Linux Enterprise 15 system:
# firewall-cmd --get-service
amanda-client bacula bacula-client dhcp dhcpv6 dhcpv6-client dns ftp
high-availability http https imaps ipp ipp-client ipsec kerberos kpasswd
ldap ldaps libvirt libvirt-tls mdns mountd ms-wbt mysql nfs ntp openvpn
pmcd pmproxy pmwebapi pmwebapis pop3s postgresql proxy-dhcp radius rpc-bind
samba samba-client smtp ssh telnet tftp tftp-client transmission-client
vnc-server wbem-https
Finally to view the network zones that will be active after the next firewalld service reload, enter the following command as root:
# firewall-cmd --get-service --permanent

Rule   Install firewalld Package   [ref]

The firewalld package can be installed with the following command:
$ sudo zypper install firewalld
Rationale:
The firewalld package should be installed to provide access control methods.
Severity: 
medium
Rule ID:xccdf_org.ssgproject.content_rule_package_firewalld_installed
Identifiers and References

Identifiers:  CCE-85698-9

References:  CCI-002314, CM-7, CM-7.1(iii), CM-7(b), AC-17(1), SRG-OS-000096-GPOS-00050, SRG-OS-000297-GPOS-00115