From f47345986e754ca384915b2862c86f91d153a27d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 11 Mar 2024 11:55:06 +0000 Subject: [PATCH 01/62] initial v3.0.0 Signed-off-by: Mark Bolwell --- Changelog.md | 42 +- README.md | 10 +- defaults/main.yml | 987 ++++++++++-------- files/etc/systemd/system/tmp.mount | 25 + handlers/main.yml | 101 +- meta/main.yml | 3 +- tasks/LE_audit_setup.yml | 12 +- tasks/auditd.yml | 6 +- tasks/main.yml | 141 ++- tasks/parse_etc_password.yml | 2 +- tasks/post.yml | 19 +- tasks/post_remediation_audit.yml | 2 +- tasks/pre_remediation_audit.yml | 15 +- tasks/prelim.yml | 360 ++++--- tasks/section_1/cis_1.1.1.x.yml | 242 ++++- tasks/section_1/cis_1.1.2.1.x.yml | 90 ++ tasks/section_1/cis_1.1.2.2.x.yml | 56 + tasks/section_1/cis_1.1.2.3.x.yml | 57 + tasks/section_1/cis_1.1.2.4.x.yml | 58 + tasks/section_1/cis_1.1.2.5.x.yml | 62 ++ tasks/section_1/cis_1.1.2.6.x.yml | 61 ++ tasks/section_1/cis_1.1.2.7.x.yml | 60 ++ tasks/section_1/cis_1.1.2.x.yml | 84 -- tasks/section_1/cis_1.1.3.x.yml | 59 -- tasks/section_1/cis_1.1.4.x.yml | 60 -- tasks/section_1/cis_1.1.5.x.yml | 61 -- tasks/section_1/cis_1.1.6.x.yml | 60 -- tasks/section_1/cis_1.1.7.x.yml | 63 -- tasks/section_1/cis_1.1.8.x.yml | 43 - tasks/section_1/cis_1.1.x.yml | 53 - tasks/section_1/cis_1.10.yml | 24 - tasks/section_1/cis_1.2.x.yml | 124 ++- tasks/section_1/cis_1.3.x.yml | 84 +- tasks/section_1/cis_1.4.x.yml | 89 +- tasks/section_1/cis_1.5.1.x.yml | 154 +++ tasks/section_1/cis_1.5.x.yml | 48 - tasks/section_1/cis_1.6.1.x.yml | 135 --- tasks/section_1/cis_1.6.x.yml | 91 ++ tasks/section_1/cis_1.7.x.yml | 75 +- tasks/section_1/cis_1.8.x.yml | 237 ++++- tasks/section_1/cis_1.9.yml | 37 +- tasks/section_1/main.yml | 84 +- tasks/section_2/cis_2.1.x.yml | 51 +- tasks/section_2/cis_2.2.x.yml | 727 +++++++++---- tasks/section_2/cis_2.3.x.yml | 73 +- tasks/section_2/cis_2.4.yml | 31 - tasks/section_2/main.yml | 12 +- tasks/section_3/cis_3.1.x.yml | 129 +-- tasks/section_3/cis_3.2.x.yml | 142 ++- tasks/section_3/cis_3.3.x.yml | 291 ++++-- tasks/section_3/cis_3.4.1.x.yml | 162 +-- tasks/section_3/cis_3.4.2.x.yml | 374 +++---- tasks/section_3/cis_3.4.3.1.x.yml | 50 - tasks/section_3/cis_3.4.3.2.x.yml | 169 --- tasks/section_3/cis_3.4.3.3.x.yml | 163 --- tasks/section_3/main.yml | 44 +- tasks/section_4/cis_4.1.1.x.yml | 215 ++-- tasks/section_4/cis_4.1.2.x.yml | 65 +- tasks/section_4/cis_4.2.3.yml | 35 - tasks/section_4/cis_4.2.x.yml | 488 +++++++++ tasks/section_4/cis_4.3.x.yml | 151 +++ tasks/section_4/cis_4.3.yml | 28 - tasks/section_4/cis_4.4.1.x.yml | 37 + tasks/section_4/cis_4.4.2.x.yml | 168 +++ tasks/section_4/cis_4.4.3.1.x.yml | 131 +++ tasks/section_4/cis_4.4.3.2.x.yml | 294 ++++++ tasks/section_4/cis_4.4.3.3.x.yml | 118 +++ tasks/section_4/cis_4.4.3.4.x.yml | 174 +++ tasks/section_4/cis_4.5.1.x.yml | 196 ++++ tasks/section_4/cis_4.5.2.x.yml | 99 ++ tasks/section_4/cis_4.5.3.x.yml | 68 ++ tasks/section_4/main.yml | 73 +- .../cis_5.1.1.x.yml} | 174 ++- .../cis_5.1.2.x.yml} | 191 ++-- tasks/section_5/cis_5.1.3.yml | 30 + tasks/section_5/cis_5.1.4.yml | 37 + tasks/section_5/cis_5.1.x.yml | 171 --- tasks/section_5/cis_5.2.1.x.yml | 117 +++ tasks/section_5/cis_5.2.2.x.yml | 81 ++ .../cis_5.2.3.x.yml} | 202 ++-- tasks/section_5/cis_5.2.4.x.yml | 179 ++++ tasks/section_5/cis_5.2.x.yml | 378 ------- tasks/section_5/cis_5.3.x.yml | 181 ++-- tasks/section_5/cis_5.4.x.yml | 100 -- tasks/section_5/cis_5.5.x.yml | 121 --- tasks/section_5/cis_5.6.1.x.yml | 230 ---- tasks/section_5/cis_5.6.x.yml | 118 --- tasks/section_5/main.yml | 56 +- tasks/section_6/cis_6.1.x.yml | 468 +++++---- tasks/section_6/cis_6.2.x.yml | 647 ++++++------ tasks/section_6/main.yml | 6 +- tasks/warning_facts.yml | 2 +- templates/ansible_vars_goss.yml.j2 | 873 ++++++++++------ templates/audit/99_auditd.rules.j2 | 48 +- templates/chrony.conf.j2 | 107 +- templates/crypto_policy_RSA.j2 | 4 - .../policies/modules/NO-SHA1.pmod.j2 | 6 + .../policies/modules/NO-SSHCBC.pmod.j2 | 6 + .../policies/modules/NO-WEAKMAC.pmod.j2 | 5 + templates/etc/dconf/db/00-media-automount.j2 | 5 + templates/etc/dconf/db/00-media-autorun.j2 | 2 + templates/etc/dconf/db/00-screensaver.j2 | 9 + .../etc/dconf/db/locks/00-automount_lock.j2 | 6 + .../etc/dconf/db/locks/00-autorun_lock.j2 | 3 + .../etc/dconf/db/locks/00-screensaver_lock.j2 | 4 + templates/etc/systemd/system/tmp.mount.j2 | 2 +- templates/ntp.conf.j2 | 2 +- vars/audit.yml | 17 +- vars/main.yml | 5 +- 109 files changed, 7710 insertions(+), 5717 deletions(-) create mode 100644 files/etc/systemd/system/tmp.mount create mode 100644 tasks/section_1/cis_1.1.2.1.x.yml create mode 100644 tasks/section_1/cis_1.1.2.2.x.yml create mode 100644 tasks/section_1/cis_1.1.2.3.x.yml create mode 100644 tasks/section_1/cis_1.1.2.4.x.yml create mode 100644 tasks/section_1/cis_1.1.2.5.x.yml create mode 100644 tasks/section_1/cis_1.1.2.6.x.yml create mode 100644 tasks/section_1/cis_1.1.2.7.x.yml delete mode 100644 tasks/section_1/cis_1.1.2.x.yml delete mode 100644 tasks/section_1/cis_1.1.3.x.yml delete mode 100644 tasks/section_1/cis_1.1.4.x.yml delete mode 100644 tasks/section_1/cis_1.1.5.x.yml delete mode 100644 tasks/section_1/cis_1.1.6.x.yml delete mode 100644 tasks/section_1/cis_1.1.7.x.yml delete mode 100644 tasks/section_1/cis_1.1.8.x.yml delete mode 100644 tasks/section_1/cis_1.1.x.yml delete mode 100644 tasks/section_1/cis_1.10.yml create mode 100644 tasks/section_1/cis_1.5.1.x.yml delete mode 100644 tasks/section_1/cis_1.5.x.yml delete mode 100644 tasks/section_1/cis_1.6.1.x.yml create mode 100644 tasks/section_1/cis_1.6.x.yml delete mode 100644 tasks/section_2/cis_2.4.yml delete mode 100644 tasks/section_3/cis_3.4.3.1.x.yml delete mode 100644 tasks/section_3/cis_3.4.3.2.x.yml delete mode 100644 tasks/section_3/cis_3.4.3.3.x.yml delete mode 100644 tasks/section_4/cis_4.2.3.yml create mode 100644 tasks/section_4/cis_4.2.x.yml create mode 100644 tasks/section_4/cis_4.3.x.yml delete mode 100644 tasks/section_4/cis_4.3.yml create mode 100644 tasks/section_4/cis_4.4.1.x.yml create mode 100644 tasks/section_4/cis_4.4.2.x.yml create mode 100644 tasks/section_4/cis_4.4.3.1.x.yml create mode 100644 tasks/section_4/cis_4.4.3.2.x.yml create mode 100644 tasks/section_4/cis_4.4.3.3.x.yml create mode 100644 tasks/section_4/cis_4.4.3.4.x.yml create mode 100644 tasks/section_4/cis_4.5.1.x.yml create mode 100644 tasks/section_4/cis_4.5.2.x.yml create mode 100644 tasks/section_4/cis_4.5.3.x.yml rename tasks/{section_4/cis_4.2.1.x.yml => section_5/cis_5.1.1.x.yml} (60%) rename tasks/{section_4/cis_4.2.2.x.yml => section_5/cis_5.1.2.x.yml} (52%) create mode 100644 tasks/section_5/cis_5.1.3.yml create mode 100644 tasks/section_5/cis_5.1.4.yml delete mode 100644 tasks/section_5/cis_5.1.x.yml create mode 100644 tasks/section_5/cis_5.2.1.x.yml create mode 100644 tasks/section_5/cis_5.2.2.x.yml rename tasks/{section_4/cis_4.1.3.x.yml => section_5/cis_5.2.3.x.yml} (63%) create mode 100644 tasks/section_5/cis_5.2.4.x.yml delete mode 100644 tasks/section_5/cis_5.2.x.yml delete mode 100644 tasks/section_5/cis_5.4.x.yml delete mode 100644 tasks/section_5/cis_5.5.x.yml delete mode 100644 tasks/section_5/cis_5.6.1.x.yml delete mode 100644 tasks/section_5/cis_5.6.x.yml delete mode 100644 templates/crypto_policy_RSA.j2 create mode 100644 templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 create mode 100644 templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 create mode 100644 templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 create mode 100644 templates/etc/dconf/db/00-media-automount.j2 create mode 100644 templates/etc/dconf/db/00-media-autorun.j2 create mode 100644 templates/etc/dconf/db/00-screensaver.j2 create mode 100644 templates/etc/dconf/db/locks/00-automount_lock.j2 create mode 100644 templates/etc/dconf/db/locks/00-autorun_lock.j2 create mode 100644 templates/etc/dconf/db/locks/00-screensaver_lock.j2 diff --git a/Changelog.md b/Changelog.md index 20a34030..b3274ef3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,36 +1,18 @@ # Changes to rhel8CIS -## 1.5.16 - Based on CIS v2.0.0 +## 2.0 based on CIS 3.0.0 -- updated min ansibleversion to 2.11.1 +### This is not an upgrade for CIS v2.0.0 due to the number of changes treat as a new baseline -- changes to 5.6.1.[ 1, 2, 3] - - ability to change current users - - variables added to defaults/main.yml to enable +Inline with new CIS baseline +Rewrite and ordering of nearly all controls +Many new controls added +Authselect is now used to setup pam options +Min ansible version now 2.11.1 -- ability to choose remove for mask for nfs,rpc and rsync - -## 1.5.15 - based on CIS v2.0.0 - -### Audit - -- ability to run audit_only - - var audit_only: true - - tidy up of audit variables to var/audit.yml and some in defaults/main.ym -- goss version increased to 0.3.23 - Doesn't run with latest version 0.4+ - -- updated 5.4.1 and 5.4.2 for authselect - -- Update to 2.1.2. sysconfig for chronyd - -- Added optional control thanks to @bbaassssiiee - - #273 - ability to use crypto Future with options - optional control added - - #329 - pam remove nullok - optional control added - -- update to audit thanks you @aaosopra - - #336 - - #337 - - #338 +- variable audit_only - ability to run audit only without remediate +- New ansible-lint layout +- New variable rhel8cis_disruption_high - found in defaults/main.yml default false ## 1.5.14 based on CIS v2.0.0 @@ -189,6 +171,10 @@ Issues. - #228 Thanks to benbulll - audit binary copy var missing +<<<<<<< HEAD +======= + +>>>>>>> devel ## 1.4.0 - workflow improvements diff --git a/README.md b/README.md index 4c3ba530..399bed81 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Configure a RHEL/Rocky/AlmaLinux 8 machine to be [CIS](https://www.cisecurity.org/cis-benchmarks/) compliant -### Based on [ CIS RedHat Enterprise Linux 8 Benchmark v2.0.0 - 02-23-2022 ](https://www.cisecurity.org/cis-benchmarks/) +### Based on [ CIS RedHat Enterprise Linux 8 Benchmark v3.0.0 - 11-10-2023 ](https://www.cisecurity.org/cis-benchmarks/) --- @@ -53,6 +53,8 @@ This role was developed against a clean install of the Operating System. If you To use release version please point to main branch and relevant release for the cis benchmark you wish to work with. +If moving across major releases e.g. v2.0.0 - v3.0.0 there are significant changes to the benchmarks and controls it is suggested to start as a new standard not to upgrade. + --- ## Matching a security Level for CIS @@ -133,8 +135,8 @@ RHEL/AlmaLinux/Rocky/Oracle 8 - Other versions are not supported. - AlmaLinux/Rocky Has been tested on 8.8(enabling crypto (sections 1.10 & 1.11) breaks updating or installs : July 01 2021 - Access to download or add the goss binary and content to the system if using auditing (other options are available on how to get the content to the system.) -- Python3 -- Ansible 2.10+ +- Python3.8 +- Ansible 2.11+ - python-def (should be included in RHEL 8) - libselinux-python @@ -175,6 +177,8 @@ rhel8cis_rule_1_1_3_3 [bug 1839899](https://bugs.launchpad.net/cloud-init/+bug/1839899) +Almalinux BaseOS, EPEL and many cloud providers repositories, do not allow repo_gpgcheck on rule_1.2.3 this will cause issues during the playbook unless or a workaround is found. + ## Pipeline Testing uses: diff --git a/defaults/main.yml b/defaults/main.yml index a52598f8..724cbe4a 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -21,7 +21,9 @@ rhel8cis_level_1: true rhel8cis_level_2: true rhel8cis_selinux_disable: false -rhel8cis_legacy_boot: false + +# Some tests can have a heavy impact on systen e.g. find on all filesystems etc +rhel8cis_disruption_high: false ## Python Binary ## This is used for python3 Installations where python2 OS modules are used in ansible @@ -30,15 +32,11 @@ python2_bin: /bin/python2.7 ## Benchmark name used by audting control role # The audit variable found at the base benchmark: RHEL8-CIS -benchmark_version: v2.0.0 +benchmark_version: v3.0.0 # Whether to skip the reboot skip_reboot: true -### -### Settings for associated Audit role using Goss -### - ########################################## ### Goss is required on the remote host ### ## Refer to vars/auditd.yml for any other settings ## @@ -62,26 +60,14 @@ audit_capture_files_dir: /some/location to copy to on control node # you will need to access to either github or the file already dowmloaded get_audit_binary_method: download -## if get_audit_binary_method - copy the following needs to be updated for your environment -## it is expected that it will be copied from somewhere accessible to the control node -## e.g copy from ansible control node to remote host -audit_bin_copy_location: /some/accessible/path - # how to get audit files onto host options # options are git/copy/get_url other e.g. if you wish to run from already downloaded conf audit_content: git -# archive or copy: -audit_conf_copy: "some path to copy from" - -# get_url: -audit_files_url: "some url maybe s3?" - # Run heavy tests - some tests can have more impact on a system enabling these can have greater impact on a system audit_run_heavy_tests: true ### End Goss enablements #### -#### Detailed settings found at the end of this document #### # These variables correspond with the CIS rule IDs or paragraph numbers defined in # the CIS benchmark documents. @@ -91,76 +77,112 @@ audit_run_heavy_tests: true rhel8cis_rule_1_1_1_1: true rhel8cis_rule_1_1_1_2: true rhel8cis_rule_1_1_1_3: true -rhel8cis_rule_1_1_2_1: true -rhel8cis_rule_1_1_2_2: true -rhel8cis_rule_1_1_2_3: true -rhel8cis_rule_1_1_2_4: true -rhel8cis_rule_1_1_3_1: true -rhel8cis_rule_1_1_3_2: true -rhel8cis_rule_1_1_3_3: true -rhel8cis_rule_1_1_3_4: true -rhel8cis_rule_1_1_4_1: true -rhel8cis_rule_1_1_4_2: true -rhel8cis_rule_1_1_4_3: true -rhel8cis_rule_1_1_4_4: true -rhel8cis_rule_1_1_5_1: true -rhel8cis_rule_1_1_5_2: true -rhel8cis_rule_1_1_5_3: true -rhel8cis_rule_1_1_5_4: true -rhel8cis_rule_1_1_6_1: true -rhel8cis_rule_1_1_6_2: true -rhel8cis_rule_1_1_6_3: true -rhel8cis_rule_1_1_6_4: true -rhel8cis_rule_1_1_7_1: true -rhel8cis_rule_1_1_7_2: true -rhel8cis_rule_1_1_7_3: true -rhel8cis_rule_1_1_7_4: true -rhel8cis_rule_1_1_7_5: true -rhel8cis_rule_1_1_8_1: true -rhel8cis_rule_1_1_8_2: true -rhel8cis_rule_1_1_8_3: true -rhel8cis_rule_1_1_9: true -rhel8cis_rule_1_1_10: true +rhel8cis_rule_1_1_1_4: true +rhel8cis_rule_1_1_1_5: true +rhel8cis_rule_1_1_1_6: true +rhel8cis_rule_1_1_1_7: true +rhel8cis_rule_1_1_1_8: true + +# /tmp +rhel8cis_rule_1_1_2_1_1: true +rhel8cis_rule_1_1_2_1_2: true +rhel8cis_rule_1_1_2_1_3: true +rhel8cis_rule_1_1_2_1_4: true + +# /dev/shm +rhel8cis_rule_1_1_2_2_1: true +rhel8cis_rule_1_1_2_2_2: true +rhel8cis_rule_1_1_2_2_3: true +rhel8cis_rule_1_1_2_2_4: true + +# /home +rhel8cis_rule_1_1_2_3_1: true +rhel8cis_rule_1_1_2_3_2: true +rhel8cis_rule_1_1_2_3_3: true + +# /var +rhel8cis_rule_1_1_2_4_1: true +rhel8cis_rule_1_1_2_4_2: true +rhel8cis_rule_1_1_2_4_3: true + +# /var/tmp +rhel8cis_rule_1_1_2_5_1: true +rhel8cis_rule_1_1_2_5_2: true +rhel8cis_rule_1_1_2_5_3: true +rhel8cis_rule_1_1_2_5_4: true + +# /var/log +rhel8cis_rule_1_1_2_6_1: true +rhel8cis_rule_1_1_2_6_2: true +rhel8cis_rule_1_1_2_6_3: true +rhel8cis_rule_1_1_2_6_4: true + +# /var/log/audit +rhel8cis_rule_1_1_2_7_1: true +rhel8cis_rule_1_1_2_7_2: true +rhel8cis_rule_1_1_2_7_3: true +rhel8cis_rule_1_1_2_7_4: true + +# DNF - Patching rhel8cis_rule_1_2_1: true rhel8cis_rule_1_2_2: true rhel8cis_rule_1_2_3: true rhel8cis_rule_1_2_4: true +rhel8cis_rule_1_2_5: true + +# bootloader grub rhel8cis_rule_1_3_1: true rhel8cis_rule_1_3_2: true + +# kernel sysctl and coredumps rhel8cis_rule_1_4_1: true rhel8cis_rule_1_4_2: true rhel8cis_rule_1_4_3: true -rhel8cis_rule_1_5_1: true -rhel8cis_rule_1_5_2: true -rhel8cis_rule_1_5_3: true +rhel8cis_rule_1_4_4: true + +# SElinux +rhel8cis_rule_1_5_1_1: true +rhel8cis_rule_1_5_1_2: true +rhel8cis_rule_1_5_1_3: true +rhel8cis_rule_1_5_1_4: true +rhel8cis_rule_1_5_1_5: true +rhel8cis_rule_1_5_1_6: true +rhel8cis_rule_1_5_1_7: true +rhel8cis_rule_1_5_1_8: true + +# Crypto Policies rhel8cis_rule_1_6_1: true rhel8cis_rule_1_6_2: true -rhel8cis_rule_1_6_1_1: true -rhel8cis_rule_1_6_1_2: true -rhel8cis_rule_1_6_1_3: true -rhel8cis_rule_1_6_1_4: true -rhel8cis_rule_1_6_1_5: true -rhel8cis_rule_1_6_1_6: true -rhel8cis_rule_1_6_1_7: true -rhel8cis_rule_1_6_1_8: true +rhel8cis_rule_1_6_3: true +rhel8cis_rule_1_6_4: true + +# MOTD and messages rhel8cis_rule_1_7_1: true rhel8cis_rule_1_7_2: true rhel8cis_rule_1_7_3: true rhel8cis_rule_1_7_4: true rhel8cis_rule_1_7_5: true rhel8cis_rule_1_7_6: true + +# Gnome desktop rhel8cis_rule_1_8_1: true rhel8cis_rule_1_8_2: true rhel8cis_rule_1_8_3: true rhel8cis_rule_1_8_4: true rhel8cis_rule_1_8_5: true -rhel8cis_rule_1_9: true -rhel8cis_rule_1_10: true -rhel8cis_rule_1_11: true +rhel8cis_rule_1_8_6: true +rhel8cis_rule_1_8_7: true +rhel8cis_rule_1_8_8: true +rhel8cis_rule_1_8_9: true +rhel8cis_rule_1_8_10: true # Section 2 rules +# time sync rhel8cis_rule_2_1_1: true rhel8cis_rule_2_1_2: true +rhel8cis_rule_2_1_3: true + +# Server services rhel8cis_rule_2_2_1: true rhel8cis_rule_2_2_2: true rhel8cis_rule_2_2_3: true @@ -181,21 +203,29 @@ rhel8cis_rule_2_2_17: true rhel8cis_rule_2_2_18: true rhel8cis_rule_2_2_19: true rhel8cis_rule_2_2_20: true +rhel8cis_rule_2_2_21: true +rhel8cis_rule_2_2_22: true + +# Client services rhel8cis_rule_2_3_1: true rhel8cis_rule_2_3_2: true rhel8cis_rule_2_3_3: true rhel8cis_rule_2_3_4: true rhel8cis_rule_2_3_5: true -rhel8cis_rule_2_3_6: true -rhel8cis_rule_2_4: true # Section 3 rules +# network connectivity wifi/bluetooth/ipv6 rhel8cis_rule_3_1_1: true rhel8cis_rule_3_1_2: true rhel8cis_rule_3_1_3: true -rhel8cis_rule_3_1_4: true + +# Network Kernel module rhel8cis_rule_3_2_1: true rhel8cis_rule_3_2_2: true +rhel8cis_rule_3_2_3: true +rhel8cis_rule_3_2_4: true + +# Network Kernel Params rhel8cis_rule_3_3_1: true rhel8cis_rule_3_3_2: true rhel8cis_rule_3_3_3: true @@ -205,144 +235,206 @@ rhel8cis_rule_3_3_6: true rhel8cis_rule_3_3_7: true rhel8cis_rule_3_3_8: true rhel8cis_rule_3_3_9: true +rhel8cis_rule_3_3_10: true +rhel8cis_rule_3_3_11: true + +# Firewall rhel8cis_rule_3_4_1_1: true rhel8cis_rule_3_4_1_2: true -rhel8cis_rule_3_4_1_3: true -rhel8cis_rule_3_4_1_4: true -rhel8cis_rule_3_4_1_5: true -rhel8cis_rule_3_4_1_6: true -rhel8cis_rule_3_4_1_7: true + +# Firewall rules rhel8cis_rule_3_4_2_1: true rhel8cis_rule_3_4_2_2: true rhel8cis_rule_3_4_2_3: true rhel8cis_rule_3_4_2_4: true rhel8cis_rule_3_4_2_5: true -rhel8cis_rule_3_4_2_6: true -rhel8cis_rule_3_4_2_7: true -rhel8cis_rule_3_4_2_8: true -rhel8cis_rule_3_4_2_9: true -rhel8cis_rule_3_4_2_10: true -rhel8cis_rule_3_4_2_11: true -rhel8cis_rule_3_4_3_1_1: true -rhel8cis_rule_3_4_3_1_2: true -rhel8cis_rule_3_4_3_1_3: true -rhel8cis_rule_3_4_3_2_1: true -rhel8cis_rule_3_4_3_2_2: true -rhel8cis_rule_3_4_3_2_3: true -rhel8cis_rule_3_4_3_2_4: true -rhel8cis_rule_3_4_3_2_5: true -rhel8cis_rule_3_4_3_2_6: true -rhel8cis_rule_3_4_3_3_1: true -rhel8cis_rule_3_4_3_3_2: true -rhel8cis_rule_3_4_3_3_3: true -rhel8cis_rule_3_4_3_3_4: true -rhel8cis_rule_3_4_3_3_5: true -rhel8cis_rule_3_4_3_3_6: true - -# Section 4 rules + +## +## Section 4 rules +## +# cron rhel8cis_rule_4_1_1_1: true rhel8cis_rule_4_1_1_2: true rhel8cis_rule_4_1_1_3: true rhel8cis_rule_4_1_1_4: true +rhel8cis_rule_4_1_1_5: true +rhel8cis_rule_4_1_1_6: true +rhel8cis_rule_4_1_1_7: true +rhel8cis_rule_4_1_1_8: true + +# at rhel8cis_rule_4_1_2_1: true -rhel8cis_rule_4_1_2_2: true -rhel8cis_rule_4_1_2_3: true -rhel8cis_rule_4_1_3_1: true -rhel8cis_rule_4_1_3_2: true -rhel8cis_rule_4_1_3_3: true -rhel8cis_rule_4_1_3_4: true -rhel8cis_rule_4_1_3_5: true -rhel8cis_rule_4_1_3_6: true -rhel8cis_rule_4_1_3_7: true -rhel8cis_rule_4_1_3_8: true -rhel8cis_rule_4_1_3_9: true -rhel8cis_rule_4_1_3_10: true -rhel8cis_rule_4_1_3_11: true -rhel8cis_rule_4_1_3_12: true -rhel8cis_rule_4_1_3_13: true -rhel8cis_rule_4_1_3_14: true -rhel8cis_rule_4_1_3_15: true -rhel8cis_rule_4_1_3_16: true -rhel8cis_rule_4_1_3_17: true -rhel8cis_rule_4_1_3_18: true -rhel8cis_rule_4_1_3_19: true -rhel8cis_rule_4_1_3_20: true -rhel8cis_rule_4_1_3_21: true -rhel8cis_rule_4_2_1_1: true -rhel8cis_rule_4_2_1_2: true -rhel8cis_rule_4_2_1_3: true -rhel8cis_rule_4_2_1_4: true -rhel8cis_rule_4_2_1_5: true -rhel8cis_rule_4_2_1_6: true -rhel8cis_rule_4_2_1_7: true -rhel8cis_rule_4_2_2_1_1: true -rhel8cis_rule_4_2_2_1_2: true -rhel8cis_rule_4_2_2_1_3: true -rhel8cis_rule_4_2_2_1_4: true -rhel8cis_rule_4_2_2_2: true -rhel8cis_rule_4_2_2_3: true -rhel8cis_rule_4_2_2_4: true -rhel8cis_rule_4_2_2_5: true -rhel8cis_rule_4_2_2_6: true -rhel8cis_rule_4_2_2_7: true + +# sshd +rhel8cis_rule_4_2_1: true +rhel8cis_rule_4_2_2: true rhel8cis_rule_4_2_3: true -rhel8cis_rule_4_3: true +rhel8cis_rule_4_2_4: true +rhel8cis_rule_4_2_5: true +rhel8cis_rule_4_2_6: true +rhel8cis_rule_4_2_7: true +rhel8cis_rule_4_2_8: true +rhel8cis_rule_4_2_9: true +rhel8cis_rule_4_2_10: true +rhel8cis_rule_4_2_12: true +rhel8cis_rule_4_2_11: true +rhel8cis_rule_4_2_13: true +rhel8cis_rule_4_2_14: true +rhel8cis_rule_4_2_15: true +rhel8cis_rule_4_2_16: true +rhel8cis_rule_4_2_17: true +rhel8cis_rule_4_2_18: true +rhel8cis_rule_4_2_19: true +rhel8cis_rule_4_2_20: true +rhel8cis_rule_4_2_21: true +rhel8cis_rule_4_2_22: true + +# sudo +rhel8cis_rule_4_3_1: true +rhel8cis_rule_4_3_2: true +rhel8cis_rule_4_3_3: true +rhel8cis_rule_4_3_4: true +rhel8cis_rule_4_3_5: true +rhel8cis_rule_4_3_6: true +rhel8cis_rule_4_3_7: true + +# Pam software pkgs +rhel8cis_rule_4_4_1_1: true +rhel8cis_rule_4_4_1_2: true + +# authselect +rhel8cis_rule_4_4_2_1: true +rhel8cis_rule_4_4_2_2: true +rhel8cis_rule_4_4_2_3: true +rhel8cis_rule_4_4_2_4: true +rhel8cis_rule_4_4_2_5: true + +# pam faillock +rhel8cis_rule_4_4_3_1_1: true +rhel8cis_rule_4_4_3_1_2: true +rhel8cis_rule_4_4_3_1_3: true + +# pam pwquality +rhel8cis_rule_4_4_3_2_1: true +rhel8cis_rule_4_4_3_2_2: true +rhel8cis_rule_4_4_3_2_3: true +rhel8cis_rule_4_4_3_2_4: true +rhel8cis_rule_4_4_3_2_5: true +rhel8cis_rule_4_4_3_2_6: true +rhel8cis_rule_4_4_3_2_7: true + +# pam pwhistory +rhel8cis_rule_4_4_3_3_1: true +rhel8cis_rule_4_4_3_3_2: true +rhel8cis_rule_4_4_3_3_3: true + +# pam pam_unix +rhel8cis_rule_4_4_3_4_1: true +rhel8cis_rule_4_4_3_4_2: true +rhel8cis_rule_4_4_3_4_3: true +rhel8cis_rule_4_4_3_4_4: true + +# Shadow user settings +rhel8cis_rule_4_5_1_1: true +rhel8cis_rule_4_5_1_2: true +rhel8cis_rule_4_5_1_3: true +rhel8cis_rule_4_5_1_4: true +rhel8cis_rule_4_5_1_5: true + +# root and sys accts and env +rhel8cis_rule_4_5_2_1: true +rhel8cis_rule_4_5_2_2: true +rhel8cis_rule_4_5_2_3: true +rhel8cis_rule_4_5_2_4: true +rhel8cis_rule_4_5_2_5: true + +# User enviroment +rhel8cis_rule_4_5_3_1: true +rhel8cis_rule_4_5_3_2: true +rhel8cis_rule_4_5_3_3: true -# Section 5 rules -rhel8cis_rule_5_1_1: true -rhel8cis_rule_5_1_2: true +## +## Section 5 rules +## + +# Rsyslog +rhel8cis_rule_5_1_1_1: true +rhel8cis_rule_5_1_1_2: true +rhel8cis_rule_5_1_1_3: true +rhel8cis_rule_5_1_1_4: true +rhel8cis_rule_5_1_1_5: true +rhel8cis_rule_5_1_1_6: true +rhel8cis_rule_5_1_1_7: true + +# Journald +rhel8cis_rule_5_1_2_1_1: true +rhel8cis_rule_5_1_2_1_2: true +rhel8cis_rule_5_1_2_1_3: true +rhel8cis_rule_5_1_2_1_4: true +rhel8cis_rule_5_1_2_2: true +rhel8cis_rule_5_1_2_3: true +rhel8cis_rule_5_1_2_4: true +rhel8cis_rule_5_1_2_5: true +rhel8cis_rule_5_1_2_6: true rhel8cis_rule_5_1_3: true rhel8cis_rule_5_1_4: true -rhel8cis_rule_5_1_5: true -rhel8cis_rule_5_1_6: true -rhel8cis_rule_5_1_7: true -rhel8cis_rule_5_1_8: true -rhel8cis_rule_5_1_9: true -rhel8cis_rule_5_2_1: true -rhel8cis_rule_5_2_2: true -rhel8cis_rule_5_2_3: true -rhel8cis_rule_5_2_4: true -rhel8cis_rule_5_2_5: true -rhel8cis_rule_5_2_6: true -rhel8cis_rule_5_2_7: true -rhel8cis_rule_5_2_8: true -rhel8cis_rule_5_2_9: true -rhel8cis_rule_5_2_10: true -rhel8cis_rule_5_2_12: true -rhel8cis_rule_5_2_11: true -rhel8cis_rule_5_2_13: true -rhel8cis_rule_5_2_14: true -rhel8cis_rule_5_2_15: true -rhel8cis_rule_5_2_16: true -rhel8cis_rule_5_2_17: true -rhel8cis_rule_5_2_18: true -rhel8cis_rule_5_2_19: true -rhel8cis_rule_5_2_20: true + +# Auditd +rhel8cis_rule_5_2_1_1: true +rhel8cis_rule_5_2_1_2: true +rhel8cis_rule_5_2_1_3: true +rhel8cis_rule_5_2_1_4: true +rhel8cis_rule_5_2_2_1: true +rhel8cis_rule_5_2_2_2: true +rhel8cis_rule_5_2_2_3: true +rhel8cis_rule_5_2_2_4: true + +# auditd rules +rhel8cis_rule_5_2_3_1: true +rhel8cis_rule_5_2_3_2: true +rhel8cis_rule_5_2_3_3: true +rhel8cis_rule_5_2_3_4: true +rhel8cis_rule_5_2_3_5: true +rhel8cis_rule_5_2_3_6: true +rhel8cis_rule_5_2_3_7: true +rhel8cis_rule_5_2_3_8: true +rhel8cis_rule_5_2_3_9: true +rhel8cis_rule_5_2_3_10: true +rhel8cis_rule_5_2_3_11: true +rhel8cis_rule_5_2_3_12: true +rhel8cis_rule_5_2_3_13: true +rhel8cis_rule_5_2_3_14: true +rhel8cis_rule_5_2_3_15: true +rhel8cis_rule_5_2_3_16: true +rhel8cis_rule_5_2_3_17: true +rhel8cis_rule_5_2_3_18: true +rhel8cis_rule_5_2_3_19: true +rhel8cis_rule_5_2_3_20: true +rhel8cis_rule_5_2_3_21: true + +# auditd log perms +rhel8cis_rule_5_2_4_1: true +rhel8cis_rule_5_2_4_2: true +rhel8cis_rule_5_2_4_3: true +rhel8cis_rule_5_2_4_4: true +rhel8cis_rule_5_2_4_5: true +rhel8cis_rule_5_2_4_6: true +rhel8cis_rule_5_2_4_7: true +rhel8cis_rule_5_2_4_8: true +rhel8cis_rule_5_2_4_9: true +rhel8cis_rule_5_2_4_10: true + +# AIDE + rhel8cis_rule_5_3_1: true rhel8cis_rule_5_3_2: true rhel8cis_rule_5_3_3: true -rhel8cis_rule_5_3_4: true -rhel8cis_rule_5_3_5: true -rhel8cis_rule_5_3_6: true -rhel8cis_rule_5_3_7: true -rhel8cis_rule_5_4_1: true -rhel8cis_rule_5_4_2: true -rhel8cis_rule_5_5_1: true -rhel8cis_rule_5_5_2: true -rhel8cis_rule_5_5_3: true -rhel8cis_rule_5_5_4: true -rhel8cis_rule_5_5_5: true -rhel8cis_rule_5_6_1_1: true -rhel8cis_rule_5_6_1_2: true -rhel8cis_rule_5_6_1_3: true -rhel8cis_rule_5_6_1_4: true -rhel8cis_rule_5_6_1_5: true -rhel8cis_rule_5_6_2: true -rhel8cis_rule_5_6_3: true -rhel8cis_rule_5_6_4: true -rhel8cis_rule_5_6_5: true - -# Section 6 rules + +## +## Section 6 rules +## + +# System file perms rhel8cis_rule_6_1_1: true rhel8cis_rule_6_1_2: true rhel8cis_rule_6_1_3: true @@ -357,7 +449,8 @@ rhel8cis_rule_6_1_11: true rhel8cis_rule_6_1_12: true rhel8cis_rule_6_1_13: true rhel8cis_rule_6_1_14: true -rhel8cis_rule_6_1_15: true + +# local and usergroup rhel8cis_rule_6_2_1: true rhel8cis_rule_6_2_2: true rhel8cis_rule_6_2_3: true @@ -369,56 +462,10 @@ rhel8cis_rule_6_2_8: true rhel8cis_rule_6_2_9: true rhel8cis_rule_6_2_10: true rhel8cis_rule_6_2_11: true -rhel8cis_rule_6_2_12: true -rhel8cis_rule_6_2_13: true -rhel8cis_rule_6_2_14: true -rhel8cis_rule_6_2_15: true -rhel8cis_rule_6_2_16: true - -# Service configuration booleans set true to keep service - -# Server Services -rhel8cis_avahi_server: false -rhel8cis_bind: false -rhel8cis_cups_server: false -rhel8cis_dhcp_server: false -rhel8cis_dns_server: false -rhel8cis_dovecot_cyrus_server: false -rhel8cis_ftp_server: false -rhel8cis_httpd_server: false -rhel8cis_is_mail_server: false -rhel8cis_net_snmp_server: false -# Ability to choose between remove or mask(default) -rhel8cis_nfs_server: false -rhel8cis_nfs_mask: true -rhel8cis_nginx_server: false -rhel8cis_nis_server: false -# Ability to choose between remove or mask(default) -rhel8cis_rpc_server: false -rhel8cis_rpc_mask: true -# Ability to choose between remove or mask(default) -rhel8cis_rsync_server: false -rhel8cis_rsync_mask: true -rhel8cis_samba_server: false -rhel8cis_squid_server: false -rhel8cis_telnet_server: false -rhel8cis_tftp_server: false -rhel8cis_vsftpd_server: false -rhel8cis_xinetd_server: false - -# Client Services - -rhel8cis_ypbind_required: false -rhel8cis_rsh_required: false -rhel8cis_talk_required: false -rhel8cis_telnet_required: false -rhel8cis_openldap_clients_required: false -rhel8cis_tftp_client: false - -rhel8cis_allow_autofs: false +## ## Section 1 vars - +## # 1.1.2.2 # 1.1.2.3 # 1.1.2.4 @@ -428,36 +475,117 @@ rhel8cis_allow_autofs: false # If set true uses the tmp.mount service else using fstab configuration rhel8cis_tmp_svc: false -# 1.2.1 -# This is the login information for your RedHat Subscription -# DO NOT USE PLAIN TEXT PASSWORDS!!!!! -# The intent here is to use a password utility like Ansible Vault here -rhel8cis_rh_sub_user: user -rhel8cis_rh_sub_password: password # pragma: allowlist secret - -# 1.2.2 -# Do you require rhnsd -# RedHat Satellite Subscription items -rhel8cis_rhnsd_required: false - -# xinetd required -rhel8cis_xinetd_required: false +# 1.2 patch system +rhel8cis_apply_installed_kernel_limit: false +rhel8cis_installed_kernel_limit: 2 -# 1.4.1 Bootloader password +# 1.3 Bootloader password rhel8cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret rhel8cis_bootloader_password: random # pragma: allowlist secret rhel8cis_set_boot_pass: false -# 1.9 patch system -rhel8cis_apply_installed_kernel_limit: false -rhel8cis_installed_kernel_limit: 2 +# 1.5 SELinux policy +rhel8cis_selinux_state: enforcing +# Configure SELinux to meet or exceed the default targeted policy, which constrains daemons and system software only. +# Valid Inputs: targeted or mls +rhel8cis_selinux_policy: targeted -# 1.10/1.11 Set crypto policy (LEGACY, DEFAULT, FUTURE, FIPS) -# Control 1.10 states do not use LEGACY and control 1.11 says to use FUTURE or FIPS. +# 1.6 Set crypto policy (LEGACY, DEFAULT, FUTURE, FIPS) rhel8cis_crypto_policy: 'DEFAULT' # Added module to be allowed as default setting (Allowed options in vars/main.yml) rhel8cis_crypto_policy_module: '' +# 1.7 +# Warning Banner Content (issue, issue.net, motd) +rhel8cis_warning_banner: | + Authorized uses only. All activity may be monitored and reported. +# End Banner + +# 1.8 Gnome Desktop +# Whether or not to run tasks related to auditing/patching the desktop environment +rhel8cis_gui: false +rhel8cis_dconf_db_name: local +rhel8cis_screensaver_idle_delay: 900 # Set max value for idle-delay in seconds (between 1 and 900) +rhel8cis_screensaver_lock_delay: 5 # Set max value for lock-delay in seconds (between 0 and 5) +## +## Section 2 vars +## +# 2.1.1 Time Synchronization - Either chrony or ntp +rhel8cis_time_synchronization: chrony + +# Time Synchronization servers - used in template file chrony.conf.j2 +rhel8cis_time_synchronization_servers: + - 0.pool.ntp.org + - 1.pool.ntp.org + - 2.pool.ntp.org + - 3.pool.ntp.org + +rhel8cis_chrony_server_options: "minpoll 8" +rhel8cis_ntp_server_options: "iburst" + +# Service configuration +# Options are +# true to leave installed if exists not changes take place +# false - this removes the package +# mask - if a dependancy for product so cannot be removed +# Server Services +rhel8cis_autofs_services: false +rhel8cis_autofs_mask: true +rhel8cis_avahi_server: false +rhel8cis_avahi_mask: false +rhel8cis_dhcp_server: false +rhel8cis_dhcp_mask: false +rhel8cis_dns_server: false +rhel8cis_dns_mask: false +rhel8cis_dnsmasq_server: false +rhel8cis_dnsmasq_mask: false +rhel8cis_samba_server: false +rhel8cis_samba_mask: false +rhel8cis_ftp_server: false +rhel8cis_ftp_mask: false +rhel8cis_message_server: false # This is for messaging dovecot and cyrus-imap +rhel8cis_message_mask: false +rhel8cis_nfs_server: true +rhel8cis_nfs_mask: true +rhel8cis_nis_server: true # set to mask if nis client required +rhel8cis_nis_mask: false +rhel8cis_print_server: false # replaces cups +rhel8cis_print_mask: false +rhel8cis_rpc_server: true +rhel8cis_rpc_mask: true +rhel8cis_rsync_server: false +rhel8cis_rsync_mask: false +rhel8cis_net_snmp_server: false +rhel8cis_net_snmp_mask: false +rhel8cis_telnet_server: false +rhel8cis_telnet_mask: false +rhel8cis_tftp_server: false +rhel8cis_tftp_mask: false +rhel8cis_squid_server: false +rhel8cis_squid_mask: false +rhel8cis_httpd_server: false +rhel8cis_httpd_mask: false +rhel8cis_nginx_server: false +rhel8cis_nginx_mask: false +rhel8cis_xinetd_server: false +rhel8cis_xinetd_mask: false +rhel8cis_xwindow_server: false # will remove mask not an option +rhel8cis_is_mail_server: false + +# Client Services +rhel8cis_ftp_client: false +rhel8cis_openldap_clients_required: false +rhel8cis_ypbind_required: false # Same package as NIS server +rhel8cis_telnet_required: false +rhel8cis_tftp_client: false + +## +## Section 3 vars +## + +rhel8cis_bluetooth_service: false +rhel8cis_bluetooth_mask: false + # System network parameters (host only OR host and router) rhel8cis_is_router: false @@ -466,7 +594,7 @@ rhel8cis_ipv6_required: true rhel8cis_ipv6_sysctl_force: true -## Optional - Understand the impact of making the following controls to true +## Optional - Understand the impact of making the following two control to true # By default, we do not disable IPv6 on localhost, as it's important for multiple # components. If you want to disable it anyway, change the following # value to true refer https://access.redhat.com/solutions/8709 @@ -477,258 +605,210 @@ rhel8cis_ipv6_disable_localhost: false rhel8cis_ipv6_sshd_disable: false # disable chrony on ipv6 rhel8cis_ipv6_chrony_disable: false -## -# Pam Change remove null ok from system/password-auth files manual change for 5.4.1 if not using authselect -rhel8cis_remove_nullok: true -# Allow override of crypto polices tyo enable some alternate repos etc when policy is FIPS or FUTURE -rhel8cis_optional_crypto_module: false -rhel8cis_optional_key_exchange: 'ECDHE RSA DHE DHE-RSA PSK DHE-PSK ECDHE-PSK ECDHE-GSS DHE-GSS' -rhel8cis_optional_rsa_size: 2048 - -# AIDE -rhel8cis_config_aide: true -# AIDE cron settings -rhel8cis_aide_cron: - cron_user: root - cron_file: /etc/cron.d/cis_aide - aide_job: '/usr/sbin/aide --check' - aide_minute: 0 - aide_hour: 5 - aide_day: '*' - aide_month: '*' - aide_weekday: '*' - -# SELinux policy - -# SELinux can run in one of three modes: disabled, permissive, or enforcing: -# CIS strongly discourages disabled -# NOTE: -# Section 1.6.1.5 forces Enforcing to be set. So If rhel8cis_rule_1_6_1_3: true -# make sure enforcing is set below for idempotency for taks 1.6.1.3 - 5 -rhel8cis_selinux_state: enforcing -# Configure SELinux to meet or exceed the default targeted policy, which constrains daemons and system software only. -# Valid Inputs: targeted or mls -rhel8cis_selinux_policy: targeted - -# Whether or not to run tasks related to auditing/patching the desktop environment -rhel8cis_gui: false # Set to 'true' if X Windows is needed in your environment rhel8cis_xwindows_required: false -# 2.1.1 Time Synchronization - Either chrony or ntp -rhel8cis_time_synchronization: chrony - -# 2.2.1.2 Time Synchronization servers - used in template file chrony.conf.j2 -rhel8cis_time_synchronization_servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 2.pool.ntp.org - - 3.pool.ntp.org - -# rhel8cis_ansible_chrony_managed uses the template built into this remediation to be copied to /etc/chrony.conf -# If you are using your own self managed /etc/chrony.conf set this to false. -rhel8cis_chrony_ansible_managed: true - -rhel8cis_chrony_server_options: "minpoll 8" -rhel8cis_ntp_server_options: "iburst" - ## Section3 vars # default location for the sysctl overrides. rhel8cis_sysctl_file: /etc/sysctl.d/99_cis.conf -# Firewall Service - either firewalld, iptables, or nftables -rhel8cis_firewall: firewalld +# Firewall Service - either firewalld or nftables +rhel8cis_firewall: 'firewalld' -# 3.4.1.5 Default zone setting rhel8cis_default_zone: public -# 3.4.2.5 Zone and Interface setting -rhel8cis_int_zone: customezone -rhel8cis_interface: eth0 - -rhel8cis_firewall_services: - - cockpit - - dhcpv6-client - - ssh - -# 3.4.2.5 Set nftables new table create -# 3.4.2.6 -# 3.4.2.7 -# 3.4.2.8 -# 3.4.2.9 -# 3.4.2.11 rhel8cis_nft_tables_autonewtable: true rhel8cis_nft_tables_tablename: filter # 3.4.2.6 Set nftables new chain create rhel8cis_nft_tables_autochaincreate: true -# Warning Banner Content (issue, issue.net, motd) -rhel8cis_warning_banner: | - Authorized uses only. All activity may be monitored and reported. -# End Banner - -## Section4 vars - -update_audit_template: false - -rhel8cis_auditd: - space_left_action: email - action_mail_acct: root - admin_space_left_action: halt - max_log_file_action: keep_logs - -# This can be used to configure other keys in auditd.conf -rhel8cis_auditd_extra_conf: {} -# Example: -# rhel8cis_auditd_extra_conf: -# admin_space_left: '10%' - -rhel8cis_logrotate: "daily" - -# The audit_back_log_limit value should never be below 8192 -rhel8cis_audit_back_log_limit: 8192 - -# The max_log_file parameter should be based on your sites policy -rhel8cis_max_log_file_size: 10 - -# OS logging system - either rsyslog or journald or other if 3rd party tool -rhel8cis_syslog: rsyslog -rhel8cis_rsyslog_ansiblemanaged: true - -# RHEL-08-4.2.1.4/4.2.1.5 remote and destination log server name -rhel8cis_remote_log_server: logagg.example.com - -# 4.2.1.5, 4.2.2.1.3, 4.2.2.1.4 -rhel8cis_system_is_log_server: false - -# 4.2.2.1.2 -# rhel8cis_journal_upload_url is the ip address to upload the journal entries to -rhel8cis_journal_upload_url: 192.168.50.42 -# The paths below have the default paths/files, but allow user to create custom paths/filenames -rhel8cis_journal_upload_serverkeyfile: "/etc/ssl/private/journal-upload.pem" -rhel8cis_journal_servercertificatefile: "/etc/ssl/certs/journal-upload.pem" -rhel8cis_journal_trustedcertificatefile: "/etc/ssl/ca/trusted.pem" - -# 4.2.2.1 -# The variables below related to journald, please set these to your site specific values -# rhel8cis_journald_systemmaxuse is the max amount of disk space the logs will use -rhel8cis_journald_systemmaxuse: 10M -# rhel8cis_journald_systemkeepfree is the amount of disk space to keep free -rhel8cis_journald_systemkeepfree: 100G -rhel8cis_journald_runtimemaxuse: 10M -rhel8cis_journald_runtimekeepfree: 100G -# rhel8cis_journald_MaxFileSec is how long in time to keep log files. Values are Xm, Xh, Xday, Xweek, Xmonth, Xyear, for example 2week is two weeks -rhel8cis_journald_maxfilesec: 1month - -# 4.2.3 logrotate configuration -# change to true if you wish to change logrotate.d conf files -allow_logrotate_conf_umask_updates: false - +####### ## Section5 vars - +###### +## If using the allow/deny user groups options +rhel8cis_sshd_limited: false rhel8cis_sshd: - clientalivecountmax: 0 - clientaliveinterval: 900 + clientalivecountmax: 3 + clientaliveinterval: 15 logingracetime: 60 + loglevel: INFO + macs: '-hmac-md5,hmac-md5-96,hmac-ripemd160,hmac-sha1-96,umac-64@openssh.com,hmac-md5-etm@openssh.com,hmac-md5-96-etm@openssh.com,hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,umac-64-etm@openssh.com' + maxauthtries: 4 + maxsessions: 10 + maxstartups: "10:30:60" + ciphers: '-3des-cbc,aes128-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se' + kex: '-diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1' # WARNING: make sure you understand the precedence when working with these values!! + ## Only runs if value rhel8cis_sshd_limited is true # allowusers: # allowgroups: systems dba # denyusers: # denygroups: + +# 4.3. sudo +rhel8cis_sudolog_location: "/var/log/sudo.log" +rhel8cis_sudo_timestamp_timeout: 15 + +## PAM +# 4.4.2.x +# Do not use authselect if: +# Your host is part of Linux Identity Management. +# Joining your host to an IdM domain with the ipa-client-install command automatically configures SSSD authentication on your host. +# Your host is part of Active Directory via SSSD. +# Calling the realm join command to join your host to an Active Directory domain automatically configures SSSD authentication on your host. +rhel8cis_allow_authselect_updates: false +## +rhel8cis_authselect_pkg_update: false # NOTE the risks if system is using SSSD or using ipa-client-install +rhel8cis_authselect_custom_profile_create: false +rhel8cis_authselect_custom_profile_select: false +rhel8cis_authselect: + custom_profile_name: 'cis_example_profile' + default_file_to_copy: "sssd --symlink-meta" + options: with-sudo with-faillock without-nullok with-pwhistory + rhel8cis_pam_faillock: attempts: 5 + deny: 5 interval: 900 unlock_time: 900 - fail_for_root: 'no' - remember: 5 - pwhash: sha512 + root_unlock_time: 60 + # Choose options below for root options + root_option: even_deny_root + # root_option: "root_unlock_time = {{ root_unlock_time }}" + +rhel8cis_pam_pwquality: + difok: 2 + maxrepeat: 3 + maxseq: 3 + minlen: 14 + minclass: 4 -# 5.2.5 SSH LogLevel setting. Options are INFO or VERBOSE -rhel8cis_ssh_loglevel: INFO +rhel8cis_pam_pwhistory: + remember: 24 -# 5.2.19 SSH MaxSessions setting. Must be 10 or less -rhel8cis_ssh_maxsessions: 10 +rhel8cis_pam_pwhash: sha512 -# 5.3.1 Enable automation to create custom profile settings, using the settings above -rhel8cis_authselect_custom_profile_create: false +rhel8cis_pass: + inactive: 30 + max_days: 365 # Max 365 + min_days: 7 + warn_age: 7 -# 5.3.2 Enable automation to select custom profile options, using the settings above -rhel8cis_authselect_custom_profile_select: false +## Set the following to true if you wish to adjust accounts greater than rhel8cis_pass['max_days'] +rhel8cis_4_5_1_2_set_max_expiry: false -# 5.3.3 sudo log location variable -rhel8cis_sudolog_location: "/var/log/sudo.log" +## Add users to be skipped if required +rhel8cis_4_5_1_2_user_skip_list: + root -# 5.3.6 rhel8cis_sudo_timestamp_timeout is the timeout set to authentication in minutes -# To conform to CIS standards this needs to be 15 minutes or less -rhel8cis_sudo_timestamp_timeout: 15 +rhel8cis_root_umask: '0027' # 0027 or more restrictive -# 5.3.7 +rhel8cis_shell_session_timeout: + file: /etc/profile.d/tmout.sh + timeout: 900 + +# sugroup rhel8cis_sugroup: sugroup # wheel users list rhel8cis_sugroup_users: "root" -# 5.4.1/5.4.2 Custom authselect profile settings. Settings in place now will fail, they are place holders from the control example -# Due to the way many multiple options and ways to configure this control needs to be enabled and settings adjusted to minimise risk -rhel8cis_use_authconfig: false -rhel8cis_authselect: - custom_profile_name: custom-profile - default_file_to_copy: "sssd --symlink-meta" - options: with-sudo with-faillock without-nullok - # Its not provider recommended to run changes to pam files manually that affects authentication # This control needs to be set to ACCEPT this so that the changes do take place # Any other value does nothing rhel8cis_pamd_manual_risks: NEVER -# 5.6.1.x -rhel8cis_pass: - max_days: 365 - min_days: 7 - warn_age: 7 - -# 5.6.1.1 -## Set the following to true if you wish to adjust accounts greater than rhel8cis_pass['max_days'] -rhel8cis_5_6_1_1_set_max_expiry: false - -## Add users to be skipped if required -rhel8cis_5_6_1_1_user_skip_list: - root - -# 5.6.1.2 -## Set the following to true if you wish to adjust accounts greater than rhel8cis_pass['min_days'] -rhel8cis_5_6_1_1_set_min_days_change: false - -# 5.6.1.3 -## Set the following to true if you wish to adjust accounts greater than rhel8cis_pass['warn_age'] -rhel8cis_5_6_1_3_set_warn_age_change: false - -# 5.6.1.4 rhel8cis_inactivelock: lock_days: 30 -# 5.6.1.5 Allow ansible to expire password for account with a last changed date in the future. False will just display users in violation, true will expire those users passwords +# Allow ansible to expire password for account with a last changed date in the future. False will just display users in violation, true will expire those users passwords rhel8cis_futurepwchgdate_autofix: true -## PAM -rhel8cis_pam_password: - minlen: 14 - minclass: 4 - # This is a dynamic check but can be overridden here marking it as false and uncomment rhel8uid_info_dynamic: true # rhel8uid_interactive_uid_start: 1000 # rhel8uid_interactive_uid_stop: 60000 -# 5.6.3 -# Session timeout setting file (TMOUT setting can be set in multiple files) -# Timeout value is in seconds. (60 seconds * 10 = 600) -rhel8cis_shell_session_timeout: - file: /etc/profile.d/tmout.sh - timeout: 900 +## Section5 vars + +## Preferred method of logging +## Whether rsyslog or journald preferred method for local logging +rhel8cis_syslog: rsyslog +rhel8cis_rsyslog_ansiblemanaged: true +# Set if system is the log server +rhel8cis_system_is_log_server: false + +#### remote and destination log server name +rhel8cis_remote_log_server: false +rhel8cis_remote_log_host: logagg.example.com +rhel8cis_remote_log_port: 514 +rhel8cis_remote_log_protocol: tcp +rhel8cis_remote_log_retrycount: 100 +rhel8cis_remote_log_queuesize: 1000 + +update_audit_template: false + +rhel8cis_auditd: + disk_error_action: halt + disk_full_action: halt + action_mail_acct: root + space_left_action: email + admin_space_left_action: email + max_log_file_action: keep_logs + +# This can be used to configure other keys in auditd.conf +rhel8cis_auditd_extra_conf: {} +# Example: +# rhel8cis_auditd_extra_conf: +# admin_space_left: '10%' + +rhel8cis_logrotate: "daily" + +# Journald +# rhel8cis_journal_upload_url is the ip address to upload the journal entries to +rhel8cis_journal_upload_url: 192.168.50.42 +# The paths below have the default paths/files, but allow user to create custom paths/filenames +rhel8cis_journal_upload_serverkeyfile: "/etc/ssl/private/journal-upload.pem" +rhel8cis_journal_servercertificatefile: "/etc/ssl/certs/journal-upload.pem" +rhel8cis_journal_trustedcertificatefile: "/etc/ssl/ca/trusted.pem" + +# The variables below related to journald, please set these to your site specific values +# rhel8cis_journald_systemmaxuse is the max amount of disk space the logs will use +rhel8cis_journald_systemmaxuse: 10M +# rhel8cis_journald_systemkeepfree is the amount of disk space to keep free +rhel8cis_journald_systemkeepfree: 100G +rhel8cis_journald_runtimemaxuse: 10M +rhel8cis_journald_runtimekeepfree: 100G +# rhel8cis_journald_MaxFileSec is how long in time to keep log files. Values are Xm, Xh, Xday, Xweek, Xmonth, Xyear, for example 2week is two weeks +rhel8cis_journald_maxfilesec: 1month + +# logrotate configuration +# change to true if you wish to change logrotate.d conf files +allow_logrotate_conf_umask_updates: false + +# The audit_back_log_limit value should never be below 8192 +rhel8cis_audit_back_log_limit: 8192 + +# The max_log_file parameter should be based on your sites policy +rhel8cis_max_log_file_size: 10 + +# AIDE +# aide setup via - cron, timer +rhel8cis_aide_scan: cron +rhel8cis_config_aide: true +# AIDE cron settings +rhel8cis_aide_cron: + cron_user: root + cron_file: /etc/cron.d/cis_aide + aide_job: '/usr/sbin/aide --check' + aide_minute: 0 + aide_hour: 5 + aide_day: '*' + aide_month: '*' + aide_weekday: '*' ## Section6 vars @@ -739,11 +819,12 @@ rhel8cis_rpm_audit_file: /var/tmp/rpm_file_check rhel8cis_no_world_write_adjust: true rhel8cis_passwd_label: "{{ (this_item | default(item)).id }}: {{ (this_item | default(item)).dir }}" -# 6.2.9 - adjusting symlinks in home directories -# Default in ansible is true this causes lots of issues for many users -# set as variable so can be overridden but default is not to follow. +## 6.1.12 adjust files if ungrouped +rhel8cis_ungrouped_adjust: false -rhel_08_6_2_9_follow_home_symlinks: false +## 6.1.13 Remove suid/sgid from files +rhel8cis_suid_adjust: false +rhel8cis_sgid_adjust: false # 6.2.12 rhel8cis_dotperm_ansiblemanaged: true diff --git a/files/etc/systemd/system/tmp.mount b/files/etc/systemd/system/tmp.mount new file mode 100644 index 00000000..47ca6625 --- /dev/null +++ b/files/etc/systemd/system/tmp.mount @@ -0,0 +1,25 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Temporary Directory +Documentation=man:hier(7) +Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems +ConditionPathIsSymbolicLink=!/tmp +DefaultDependencies=no +Conflicts=umount.target +Before=local-fs.target umount.target + +[Mount] +What=tmpfs +Where=/tmp +Type=tmpfs +Options=mode=1777,strictatime,noexec,nodev,nosuid + +# Make 'systemctl enable tmp.mount' work: +[Install] +WantedBy=local-fs.target diff --git a/handlers/main.yml b/handlers/main.yml index f2e6e8f1..314de2bd 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,7 +1,21 @@ --- # handlers file for RHEL8-CIS -- name: sysctl flush ipv4 route table +- name: Update_authselect + ansible.builtin.shell: authselect apply-changes + +- name: Remount_tmp + ansible.builtin.shell: mount -o remount /tmp + +- name: Systemd_restart_tmp.mount + ansible.builtin.systemd: + name: tmp.mount + daemon_reload: true + enabled: true + masked: false + state: reloaded + +- name: Sysctl_flush_ipv4_routes ansible.posix.sysctl: name: net.ipv4.route.flush value: '1' @@ -9,10 +23,8 @@ ignore_errors: true # noqa ignore-errors when: - not system_is_container - tags: - - skip_ansible_lint -- name: sysctl flush ipv6 route table +- name: Sysctl_flush_ipv6_routes ansible.posix.sysctl: name: net.ipv6.route.flush value: '1' @@ -21,117 +33,76 @@ when: - not system_is_container -- name: systemd restart tmp.mount - ansible.builtin.systemd: - name: tmp.mount - daemon_reload: true - enabled: true - masked: false - state: reloaded - -- name: systemd restart var-tmp.mount - ansible.builtin.systemd: - name: var-tmp.mount - daemon_reload: true - enabled: true - masked: false - state: reloaded - -- name: Systemd_daemon_reload - ansible.builtin.systemd: - daemon-reload: true - -- name: remount tmp - ansible.builtin.shell: mount -o remount /tmp - -- name: restart firewalld - ansible.builtin.service: - name: firewalld - state: restarted - -- name: restart xinetd - ansible.builtin.service: - name: xinetd - state: restarted - -- name: restart sshd +- name: Restart_sshd ansible.builtin.service: name: sshd state: restarted -- name: restart chronyd +- name: Restart_chronyd ansible.builtin.service: name: chronyd state: restarted -- name: restart postfix +- name: Restart_postfix ansible.builtin.service: name: postfix state: restarted -- name: reload dconf +- name: Reload_dconf ansible.builtin.shell: dconf update -- name: update auditd +- name: Update_auditd_rules ansible.builtin.template: src: audit/99_auditd.rules.j2 dest: /etc/audit/rules.d/99_auditd.rules owner: root group: root - mode: 0600 - notify: restart auditd + mode: '0600' + notify: Restart_auditd -- name: restart auditd - ansible.builtin.shell: /sbin/service auditd restart - changed_when: false - check_mode: false - failed_when: false - -- name: restart journald +- name: Restart_journald ansible.builtin.service: name: systemd-journald state: restarted -- name: restart systemd_journal_upload +- name: Restart_systemd_journal_upload ansible.builtin.service: name: systemd-journal-upload state: restarted -- name: rhel8cis_grub2cfg +- name: Rebuild_grub ansible.builtin.shell: "grub2-mkconfig -o {{ grub_cfg.stat.lnk_source }}" ignore_errors: true # noqa ignore-errors - notify: change_requires_reboot + notify: Change_requires_reboot tags: - skip_ansible_lint -- name: restart rsyslog +- name: Restart_rsyslog ansible.builtin.service: name: rsyslog state: restarted -- name: systemd_daemon_reload +- name: Systemd_daemon_reload ansible.builtin.systemd: daemon-reload: true ## Auditd tasks note order for handlers to run -- name: auditd_immutable_check +- name: Auditd_immutable_check ansible.builtin.shell: grep -c "^-e 2" /etc/audit/rules.d/99_auditd.rules changed_when: false register: auditd_immutable_check -- name: audit_immutable_fact +- name: Audit_immutable_fact ansible.builtin.debug: msg: "Reboot required for auditd to apply new rules as immutable set" - notify: change_requires_reboot + notify: Change_requires_reboot when: - auditd_immutable_check.stdout == '1' -- name: restart auditd - ansible.builtin.shell: service auditd restart - tags: - - skip_ansible_lint +- name: Restart_auditd + ansible.builtin.shell: /sbin/service auditd restart -- name: change_requires_reboot +- name: Change_requires_reboot ansible.builtin.set_fact: - change_requires_reboot: true + reboot_required: true diff --git a/meta/main.yml b/meta/main.yml index 2ffe148d..c2e2402f 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -10,7 +10,7 @@ galaxy_info: platforms: - name: EL versions: - - 8 + - '8' galaxy_tags: - system - security @@ -22,6 +22,7 @@ galaxy_info: - redhat - rhel - compliance + - complianceascode collections: - community.general - community.crypto diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index 7ef94b4a..b7c0b9ba 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -3,16 +3,18 @@ - name: Pre Audit Setup | Set audit package name block: - name: Pre Audit Setup | Set audit package name | 64bit + when: ansible_machine == "x86_64" ansible.builtin.set_fact: audit_pkg_arch_name: AMD64 - when: ansible_facts.machine == "x86_64" - name: Pre Audit Setup | Set audit package name | ARM64 + when: ansible_machine == "arm64" ansible.builtin.set_fact: audit_pkg_arch_name: ARM64 - when: ansible_facts.machine == "arm64" - name: Pre Audit Setup | Download audit binary + when: + - get_audit_binary_method == 'download' ansible.builtin.get_url: url: "{{ audit_bin_url }}{{ audit_pkg_arch_name }}" dest: "{{ audit_bin }}" @@ -20,15 +22,13 @@ group: root checksum: "{{ audit_bin_version[audit_pkg_arch_name + '_checksum'] }}" mode: '0555' - when: - - get_audit_binary_method == 'download' - name: Pre Audit Setup | Copy audit binary + when: + - get_audit_binary_method == 'copy' ansible.builtin.copy: src: "{{ audit_bin_copy_location }}" dest: "{{ audit_bin }}" mode: '0555' owner: root group: root - when: - - get_audit_binary_method == 'copy' diff --git a/tasks/auditd.yml b/tasks/auditd.yml index 1b5b4aaf..d8347680 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -9,6 +9,6 @@ mode: 0600 register: audit_rules_updated notify: - - auditd_immutable_check - - audit_immutable_fact - - restart auditd + - Auditd_immutable_check + - Audit_immutable_fact + - Restart_auditd diff --git a/tasks/main.yml b/tasks/main.yml index 126c0e6b..f4e84a6a 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -2,52 +2,76 @@ # tasks file for RHEL8-CIS - name: Check OS version and family - ansible.builtin.assert: - that: (ansible_distribution != 'CentOS' and ansible_os_family == 'RedHat' or ansible_os_family == "Rocky") and ansible_distribution_major_version is version_compare('8', '==') - fail_msg: "This role can only be run against Supported OSs. {{ ansible_distribution }} {{ ansible_distribution_major_version }} is not supported." - success_msg: "This role is running against a supported OS {{ ansible_distribution }} {{ ansible_distribution_major_version }}" when: - os_check - not system_is_ec2 tags: - always + ansible.builtin.assert: + that: (ansible_distribution != 'CentOS' and ansible_os_family == 'RedHat' or ansible_os_family == "Rocky") and ansible_distribution_major_version is version_compare('8', '==') + fail_msg: "This role can only be run against Supported OSs. {{ ansible_facts.distribution }} {{ ansible_facts.distribution_major_version }} is not supported." + success_msg: "This role is running against a supported OS {{ ansible_facts.distribution }} {{ ansible_distribution_major_version }}" - name: Check ansible version + tags: + - always ansible.builtin.assert: that: ansible_version.full is version_compare(min_ansible_version, '>=') fail_msg: "You must use Ansible {{ min_ansible_version }} or greater" success_msg: "This role is running a supported version of ansible {{ ansible_version.full }} >= {{ min_ansible_version }}" - tags: - - always - name: Check crypto-policy input - ansible.builtin.assert: - that: rhel8cis_crypto_policy in rhel8cis_allowed_crypto_policies when: - - rhel8cis_rule_1_10 + - rhel8cis_rule_1_6_1 tags: - - rule_1.10 + - rule_1.6.1 + ansible.builtin.assert: + that: rhel8cis_crypto_policy in rhel8cis_allowed_crypto_policies - name: Check crypto-policy module input - ansible.builtin.assert: - that: rhel8cis_crypto_policy_module in rhel8cis_allowed_crypto_policies_modules when: - - rhel8cis_rule_1_10 + - rhel8cis_rule_1_6_1 - rhel8cis_crypto_policy_module | length > 0 tags: - - rule_1.10 + - rule_1.6.1 + ansible.builtin.assert: + that: rhel8cis_crypto_policy_module in rhel8cis_allowed_crypto_policies_modules - name: Check rhel8cis_bootloader_password_hash variable has been changed + when: + - rhel8cis_set_boot_pass + - rhel8cis_rule_1_4_1 + tags: + - always ansible.builtin.assert: that: rhel8cis_bootloader_password_hash.find('grub.pbkdf2.sha512') != -1 and rhel8cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret msg: "This role will not be able to run single user password commands as rhel8cis_bootloader_password_hash variable has not been set correctly" # pragma: allowlist secret + +- name: Ensure root password is set when: - - rhel8cis_set_boot_pass - - rhel8cis_rule_1_4_1 + - rhel8cis_rule_4_5_2_4 tags: - always + block: + - name: Ensure root password is set + ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)" + changed_when: false + failed_when: false + register: root_passwd_set + + - name: Ensure root password is set + ansible.builtin.assert: + that: root_passwd_set.rc == 0 + fail_msg: "You have rule 4.5.2.4 enabled this requires that you have a root password set" + success_msg: "You have a root password set" - name: Setup rules if container + when: + - ansible_connection == 'docker' or + ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] + tags: + - container_discovery + - always block: - name: Discover and set container variable if required ansible.builtin.set_fact: @@ -58,18 +82,16 @@ file: "{{ container_vars_file }}" - name: Output if discovered is a container - ansible.builtin.debug: - msg: system has been discovered as a container when: - system_is_container - when: - - ansible_connection == 'docker' or - ansible_virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] - tags: - - container_discovery - - always + ansible.builtin.debug: + msg: system has been discovered as a container - name: "Check password set for {{ ansible_user }}" + when: + - ansible_env.SUDO_USER is defined + - not system_is_ec2 + - not audit_only block: - name: Capture current password state of connecting user" ansible.builtin.shell: "grep {{ ansible_env.SUDO_USER }} /etc/shadow | awk -F: '{print $2}'" @@ -85,126 +107,135 @@ success_msg: "You have a password set for the {{ ansible_env.SUDO_USER }} user" vars: sudo_password_rule: rhel8cis_rule_5_3_4 # pragma: allowlist secret - when: - - rhel8cis_rule_5_3_4 - - ansible_env.SUDO_USER is defined - - not system_is_ec2 - tags: - - user_passwd -- name: Include preliminary steps - ansible.builtin.import_tasks: prelim.yml +- name: Include prelim tasks tags: - prelim_tasks - - always + - run_audit + ansible.builtin.import_tasks: + file: prelim.yml - name: Include audit specific variables - ansible.builtin.include_vars: audit.yml when: - run_audit or audit_only - setup_audit tags: - setup_audit - run_audit + ansible.builtin.include_vars: + file: audit.yml - name: Include pre-remediation audit tasks - ansible.builtin.import_tasks: pre_remediation_audit.yml when: - run_audit or audit_only - setup_audit tags: - run_audit + ansible.builtin.import_tasks: + file: pre_remediation_audit.yml - name: Gather the package facts after prelim - ansible.builtin.package_facts: - manager: auto tags: - always + ansible.builtin.package_facts: + manager: auto - name: Include OS specific variables - ansible.builtin.include_vars: "{{ ansible_distribution }}.yml" tags: - always + ansible.builtin.include_vars: + file: "{{ ansible_distribution }}.yml" - name: Capture /etc/password variables - ansible.builtin.import_tasks: parse_etc_password.yml when: - rhel8cis_section5 or rhel8cis_section6 tags: - always + ansible.builtin.import_tasks: + file: parse_etc_password.yml - name: Run Section 1 tasks - ansible.builtin.import_tasks: section_1/main.yml when: - rhel8cis_section1 tags: - rhel8cis_section1 + ansible.builtin.import_tasks: + file: section_1/main.yml - name: Run Section 2 tasks - ansible.builtin.import_tasks: section_2/main.yml when: - rhel8cis_section2 tags: - rhel8cis_section2 + ansible.builtin.import_tasks: + file: section_2/main.yml - name: Run Section 3 tasks - ansible.builtin.import_tasks: section_3/main.yml when: - rhel8cis_section3 tags: - rhel8cis_section3 + ansible.builtin.import_tasks: + file: section_3/main.yml - name: Run Section 4 tasks - ansible.builtin.import_tasks: section_4/main.yml when: - rhel8cis_section4 tags: - rhel8cis_section4 + ansible.builtin.import_tasks: + file: section_4/main.yml - name: run Section 5 tasks - ansible.builtin.import_tasks: section_5/main.yml when: - rhel8cis_section5 tags: - rhel8cis_section5 + ansible.builtin.import_tasks: + file: section_5/main.yml - name: Run Section 6 tasks - ansible.builtin.import_tasks: section_6/main.yml when: - rhel8cis_section6 tags: - rhel8cis_section6 + ansible.builtin.import_tasks: + file: section_6/main.yml - name: Run auditd logic - ansible.builtin.import_tasks: auditd.yml when: - update_audit_template tags: - always + ansible.builtin.import_tasks: + file: auditd.yml -- name: run post remediation tasks - ansible.builtin.import_tasks: post.yml +- name: Run post remediation tasks tags: - post_tasks - always - -- name: Run post audit ansible.builtin.import_tasks: - file: post_remediation_audit.yml + file: post.yml + +- name: Run post_remediation audit when: - run_audit + tags: + - run_audit + ansible.builtin.import_tasks: + file: post_remediation_audit.yml - name: Show Audit Summary - ansible.builtin.debug: - msg: "{{ audit_results.split('\n') }}" when: - run_audit tags: - run_audit + ansible.builtin.debug: + msg: "{{ audit_results.split('\n') }}" - name: Output Warning count and control IDs affected - ansible.builtin.debug: - msg: "You have {{ warn_count }} warning(s) that require investigating that are related to the following benchmark ID(s) {{ warn_control_list }}" tags: - always + ansible.builtin.debug: + msg: "You have {{ warn_count }} warning(s) that require investigating that are related to the following benchmark ID(s) {{ warn_control_list }}" diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 3c791695..1a653353 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -15,7 +15,7 @@ vars: ld_passwd_regex: >- ^(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*) - ld_passwd_yaml: | + ld_passwd_yaml: | # pragma: allowlist secret id: >-4 \g password: >-4 diff --git a/tasks/post.yml b/tasks/post.yml index 22f542bc..d981fcf8 100644 --- a/tasks/post.yml +++ b/tasks/post.yml @@ -12,31 +12,32 @@ - name: POST | reboot system if changes require it and not skipped block: - name: POST | Reboot system if changes require it and not skipped - ansible.builtin.reboot: when: - - change_requires_reboot + - reboot_required - not skip_reboot + ansible.builtin.reboot: - name: POST | Warning a reboot required but skip option set + when: + - reboot_required + - skip_reboot ansible.builtin.debug: msg: "Warning!! changes have been made that require a reboot to be implemented but skip reboot was set - Can affect compliance check results" changed_when: true - when: - - change_requires_reboot - - skip_reboot - name: "POST | Warning a reboot required but skip option set | warning count" - ansible.builtin.import_tasks: warning_facts.yml when: - - change_requires_reboot + - reboot_required - skip_reboot + ansible.builtin.import_tasks: + file: warning_facts.yml vars: warn_control_id: Reboot_required tags: - always - name: If Warning count is 0 set fact - ansible.builtin.set_fact: - control_number: "Congratulation None Found" when: - warn_count == '0' + ansible.builtin.set_fact: + control_number: "Congratulation None Found" diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 2c51bbb0..eb01bc75 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -1,7 +1,7 @@ --- - name: Post Audit | Run post_remediation {{ benchmark }} audit - ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" + ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ post_audit_outfile }} -g {{ group_names }}" changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index e3a261e7..5f2560e4 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -5,7 +5,8 @@ - setup_audit tags: - setup_audit - ansible.builtin.include_tasks: LE_audit_setup.yml + ansible.builtin.include_tasks: + file: LE_audit_setup.yml - name: Pre Audit Setup | Ensure {{ audit_conf_dir }} exists ansible.builtin.file: @@ -60,24 +61,23 @@ register: goss_available - name: Pre Audit Setup | If audit ensure goss is available - when: - - not goss_available.stat.exists ansible.builtin.assert: + that: goss_available.stat.exists msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}" - name: Pre Audit Setup | Copy ansible default vars values to test audit + when: + - run_audit tags: - goss_template - run_audit - when: - - run_audit ansible.builtin.template: src: ansible_vars_goss.yml.j2 dest: "{{ audit_vars_path }}" mode: '0600' - name: Pre Audit | Run pre_remediation {{ benchmark }} audit - ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" + ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ pre_audit_outfile }} -g {{ group_names }}" changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" @@ -115,4 +115,5 @@ - name: Audit_Only | Run Audit Only when: - audit_only - ansible.builtin.import_tasks: audit_only.yml + ansible.builtin.import_tasks: + file: audit_only.yml diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 3b672b1b..abd4d21a 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -2,30 +2,28 @@ # Preliminary tasks that should always be run - name: "PRELIM | Add the required packages" + tags: + - always ansible.builtin.package: name: - python3-libselinux - python3-rpm state: present - tags: - - always - -- name: "PRELIM | Gather the package facts before prelim" - ansible.builtin.package_facts: - manager: auto - tags: - - always # List users in order to look files inside each home directory - name: "PRELIM | List users accounts" + tags: + - always ansible.builtin.shell: "awk -F: '{print $1}' /etc/passwd" changed_when: false check_mode: false register: users - tags: - - always - name: "PRELIM | Gather interactive user ID min and max" + when: + - rhel8uid_info_dynamic + tags: + - always block: - name: "PRELIM | Gather interactive user ID min" ansible.builtin.shell: grep ^UID_MIN /etc/login.defs | awk '{print $2}' @@ -43,41 +41,82 @@ ansible.builtin.set_fact: rhel8uid_interactive_uid_start: "{{ rhel8cis_min_uid.stdout | string }}" rhel8uid_interactive_uid_stop: "{{ rhel8cis_max_uid.stdout | string }}" - when: - - rhel8uid_info_dynamic + +- name: "PRELIM | Set facts based on boot type" tags: - always + block: + - name: "PRELIM | Check whether machine is UEFI-based" + ansible.builtin.stat: + path: /sys/firmware/efi + register: rhel_08_efi_boot -- name: "PRELIM | Gather accounts with empty password fields" - ansible.builtin.shell: "cat /etc/shadow | awk -F: '($2 == \"\" ) {j++;print $1; } END {exit j}'" + - name: "PRELIM | set legacy boot and grub path | Bios" + ansible.builtin.set_fact: + rhel8cis_legacy_boot: true + grub2_path: /etc/grub2.cfg + rhel8cis_boot_path: /boot/grub2/ + when: not rhel_08_efi_boot.stat.exists + + - name: "PRELIM | set grub fact | UEFI" + ansible.builtin.set_fact: + grub2_path: /etc/grub2-efi.cfg + rhel8cis_boot_path: "/boot/efi/EFI/{{ansible_facts.distribution | lower }}/" + when: rhel_08_efi_boot.stat.exists + +- name: "PRELIM | AUDIT | Ensure permissions on bootloader config are configured | Get grub config file stats" + ansible.builtin.stat: + path: "{{ grub2_path }}" changed_when: false - check_mode: false - register: empty_password_accounts - when: - - rhel8cis_rule_6_2_1 + register: grub_cfg tags: - always -- name: "PRELIM | Gather UID 0 accounts other than root" - ansible.builtin.shell: "cat /etc/passwd | awk -F: '($3 == 0 && $1 != \"root\") {i++;print $1 } END {exit i}'" +- name: "PRELIM | Gather the package facts before prelim" + tags: + - always + ansible.builtin.package_facts: + manager: auto + +##### Section requirements ##### +- name: "PRELIM | Section 1.1 | Create list of mount points" + tags: + - always + ansible.builtin.set_fact: + mount_names: "{{ ansible_mounts | map(attribute='mount') | list }}" + +- name: "PRELIM | Ensure /dev/shm is a separate partition | discover" + when: + - rhel8cis_rule_1_1_2_2_1 or + rhel8cis_rule_1_1_2_2_2 or + rhel8cis_rule_1_1_2_2_3 or + rhel8cis_rule_1_1_2_2_4 + tags: + - always + ansible.builtin.shell: findmnt -kn /dev/shm changed_when: false - check_mode: false - register: rhel8cis_uid_zero_accounts_except_root + failed_when: rhel8cis_dev_shm_present.rc not in [ 0, 1 ] + register: rhel8cis_dev_shm_present + +- name: "PRELIM | if systemd coredump" when: - - rhel8cis_rule_6_2_8 + - rhel8cis_rule_1_4_4 tags: - always + ansible.builtin.stat: + path: /etc/systemd/coredump.conf + register: systemd_coredump - name: "PRELIM | Ensure crypto-policies-scripts package is installed" + tags: + - always ansible.builtin.package: name: crypto-policies-scripts state: installed - when: - - rhel8cis_rule_1_10 - tags: - - always - name: "PRELIM | Gather system-wide crypto-policy settings" + tags: + - always block: - name: "PRELIM | Gather system-wide crypto-policy settings" ansible.builtin.shell: 'update-crypto-policies --show' @@ -93,176 +132,217 @@ ansible.builtin.set_fact: current_crypto_module: "{{ rhel8cis_system_wide_crypto_policy.stdout.split(':')[1] }}" when: "':' in rhel8cis_system_wide_crypto_policy.stdout" - when: - - rhel8cis_rule_1_10 - tags: - - always - -- name: "PRELIM | if systemd coredump" - ansible.builtin.stat: - path: /etc/systemd/coredump.conf - register: systemd_coredump - when: - - rhel8cis_rule_1_5_1 - tags: - - always - -- name: "PRELIM | Section 1.1 | Create list of mount points" - ansible.builtin.set_fact: - mount_names: "{{ ansible_mounts | map(attribute='mount') | list }}" - tags: - - always -- name: "PRELIM | Install dconf" - ansible.builtin.package: - name: dconf - state: present +- name: "PRELIM | Install dconf if gui" when: - "'gdm' in ansible_facts.packages" - "'dconf' not in ansible_facts.packages" - - rhel8cis_rule_1_8_2 or - rhel8cis_rule_1_8_3 or - rhel8cis_rule_1_8_5 + - rhel8cis_gui tags: - always - -- name: "PRELIM | Section 4.1 | Configure System Accounting (auditd)" ansible.builtin.package: - name: audit + name: dconf state: present - when: rhel8cis_level_2 + +- name: "PRELIM | Cron Package" tags: - always - -- name: "PRELIM | Section 5.1 | Configure cron" ansible.builtin.package: name: cronie state: present - tags: - - always - name: "PRELIM | Find all sudoers files." + when: + - rhel8cis_rule_4_3_4 or + rhel8cis_rule_4_3_5 + tags: + - always ansible.builtin.shell: "find /etc/sudoers /etc/sudoers.d/ -type f ! -name '*~' ! -name '*.*'" changed_when: false failed_when: false check_mode: false register: rhel8cis_sudoers_files - when: - - rhel8cis_rule_5_3_4 or - rhel8cis_rule_5_3_5 + +- name: "PRELIM | Check authselect package versions" tags: - always + - authselect + vars: + warn_control_id: 'authselect_pkg_version_too_low' + authselect_pkg_version: 1.2.6 + block: + - name: "PRELIM | Check authselect package versions | set fact" + when: ansible_facts.packages.authselect[0].version is version(authselect_pkg_version, '>=') + ansible.builtin.set_fact: + authselect_version: OK -- name: "PRELIM | Install authconfig" - ansible.builtin.package: - name: authconfig - state: present - when: - - rhel8cis_use_authconfig - - rhel8cis_rule_5_3_1 or - rhel8cis_rule_5_3_2 or - rhel8cis_rule_5_3_3 + - name: "PRELIM | Check authselect package versions | Warning" + when: ansible_facts.packages.authselect[0].version is version(authselect_pkg_version, '<') + ansible.builtin.debug: + msg: "Warning!! Authselect controls won't run as authselect pkg version too low" + + - name: "PRELIM | Check authselect package versions | Warning" + when: ansible_facts.packages.authselect[0].version is version(authselect_pkg_version, '<') + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "PRELIM | Check pam package versions" tags: - always + vars: + warn_control_id: 'pam_pkg_version_too_low' + pam_pkg_version: 1.3.1 + pam_pkg_release: 25 + block: + - name: "PRELIM | Check pam package versions | set fact" + when: + - ansible_facts.packages.pam[0].version is version(pam_pkg_version, '>=') + - ansible_facts.packages.pam[0].release is version (pam_pkg_release, '>=') + ansible.builtin.set_fact: + pam_version: OK -- name: "PRELIM | Set facts based on boot type" + - name: "PRELIM | Check pam package versions | Warning" + when: + - ansible_facts.packages.pam[0].version is version(pam_pkg_version, '<') + - ansible_facts.packages.pam[0].release is version (pam_pkg_release, '<') + ansible.builtin.debug: + msg: "Warning!! Authselect controls won't run as pam package version too low" + + - name: "PRELIM | Check pam package versions | Warning" + when: + - ansible_facts.packages.pam[0].version is version(pam_pkg_version, '<') + - ansible_facts.packages.pam[0].release is version (pam_pkg_release, '<') + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "PRELIM | Check authselect profile is selected" + when: + - rhel8cis_allow_authselect_updates + - rhel8cis_rule_4_4_2_1 or + rhel8cis_rule_4_4_2_2 or + rhel8cis_rule_4_4_2_3 or + rhel8cis_rule_4_4_2_4 or + rhel8cis_rule_4_4_2_5 or + rhel8cis_rule_4_4_3_1_1 or + rhel8cis_rule_4_4_3_1_2 or + rhel8cis_rule_4_4_3_1_3 + tags: + - always block: - - name: "PRELIM | Check whether machine is UEFI-based" + - name: "PRELIM | Check authselect profile name has been updated" + ansible.builtin.assert: + that: rhel8cis_authselect['custom_profile_name'] != 'cis_example_profile' + fail_msg: "You still have the default name for your authselect profile" + + - name: "PRELIM | Check authselect profile is selected" + when: not rhel8cis_authselect_custom_profile_create + ansible.builtin.shell: authselect current + changed_when: false + failed_when: authselect_running_config.rc not in [ 0, 1 ] + register: authselect_running_config + + - name: "PRELIM | Check authselect profile is selected" + ansible.builtin.assert: + that: not rhel8cis_authselect_custom_profile_create and "'example' not in rhel8cis_authselect['custom_profile_name']" or authselect_running_config is defined + success_msg: "Authselect is running and profile is selected" + fail_msg: Authselect updates have been selected there are issues with profile selection" + + - name: "PRELIM | Check profile exists if not created" ansible.builtin.stat: - path: /sys/firmware/efi - register: rhel_08_efi_boot + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}" + register: rhel8cis_4_4_2_1_profile - - name: "PRELIM | AUDIT | set legacy boot and grub path | Bios" - ansible.builtin.set_fact: - rhel8cis_legacy_boot: true - grub2_path: /etc/grub2.cfg - when: not rhel_08_efi_boot.stat.exists + - name: "PRELIM | Check authselect profile exists if not created" + when: rhel8cis_4_4_2_1_profile.stat.exists + ansible.builtin.assert: + that: not rhel8cis_authselect_custom_profile_create + success_msg: "Authselect is running and profile is selected" + fail_msg: Authselect updates have been selected but you have stated create and profile already exists" - - name: "PRELIM | set grub fact | UEFI" - ansible.builtin.set_fact: - grub2_path: /etc/grub2-efi.cfg - when: rhel_08_efi_boot.stat.exists +- name: "PRELIM | Interactive User accounts home directories" tags: - always + ansible.builtin.shell: > + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $6 }' + changed_when: false + register: interactive_users_home -- name: "PRELIM | AUDIT | Ensure permissions on bootloader config are configured | Get grub config file stats" - ansible.builtin.stat: - path: "{{ grub2_path }}" +- name: "PRELIM | Section 5.1 | Configure System Accounting (auditd)" + when: rhel8cis_level_2 + tags: + - always + ansible.builtin.package: + name: audit + state: present + +- name: "PRELIM | Gather accounts with empty password fields" + when: + - rhel8cis_rule_6_2_1 + tags: + - always + ansible.builtin.shell: "cat /etc/shadow | awk -F: '($2 == \"\" ) {j++;print $1; } END {exit j}'" changed_when: false - register: grub_cfg + check_mode: false + register: empty_password_accounts + +- name: "PRELIM | Gather UID 0 accounts other than root" + when: + - rhel8cis_rule_6_2_8 tags: - always + ansible.builtin.shell: "cat /etc/passwd | awk -F: '($3 == 0 && $1 != \"root\") {i++;print $1 } END {exit i}'" + changed_when: false + check_mode: false + register: rhel8cis_uid_zero_accounts_except_root + +##### Optional ##### - name: "PRELIM | Optional | If IPv6 disable to stop ssh listening" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: ^AddressFamily - line: AddressFamily inet - notify: restart sshd when: - rhel8cis_ipv6_sshd_disable - not rhel8cis_ipv6_required tags: - always + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: ^AddressFamily + line: AddressFamily inet + notify: Restart_sshd - name: "PRELIM | Optional | If IPv6 disable to stop chronyd listening" - ansible.builtin.lineinfile: - path: /etc/sysconfig/chronyd - regexp: ^OPTIONS="(.*)" - line: OPTIONS="\1 -4" - backrefs: true - notify: restart chronyd when: - rhel8cis_ipv6_chrony_disable - not rhel8cis_ipv6_required tags: - always + notify: Restart_chronyd + block: + - name: "PRELIM | Optional | If IPv6 disable to stop chronyd listening | Check existence" + ansible.builtin.shell: grep -E "OPTIONS=.*-4" /etc/sysconfig/chronyd + changed_when: false + failed_when: chrony_ipv6_exists.rc not in [ 0, 1] + register: chrony_ipv6_exists + + - name: "PRELIM | Optional | If IPv6 disable to stop chronyd listening" + when: chrony_ipv6_exists.stdout | length == 0 + ansible.builtin.lineinfile: + backrefs: true + path: /etc/sysconfig/chronyd + regexp: ^OPTIONS="(.*)" + line: OPTIONS="\1 -4" # Optional extra keys to extend auditd not part of CIS but can influence a system # e.g. admin_space_left: '10%' - name: PRELIM | Optional | Configure other keys for auditd.conf - ansible.builtin.lineinfile: - path: /etc/audit/auditd.conf - regexp: "^{{ item }}( |=)" - line: "{{ item }} = {{ rhel8cis_auditd_extra_conf[item] }}" - notify: restart auditd - loop: "{{ rhel8cis_auditd_extra_conf.keys() }}" when: - rhel8cis_auditd_extra_conf.keys() | length > 0 - rhel8cis_level_2 tags: - always - -# Not assigned directly to any control but a requirement - manual change for 5.4.1 if not using authselect -- name: "PRELIM | Optional | Remove the ability to login without a password" - ansible.builtin.replace: - path: "{{ item }}" - regexp: '\snullok' - replace: '' - loop: - - /etc/pam.d/system-auth - - /etc/pam.d/password-auth - when: rhel8cis_remove_nullok - -# Allow other keys to be used while setting FUTURE or FIPS in crypto Policy -# These settings may need to be changed to personal preference -- name: "PRELIM | Optional | Override Ciphers/Keys/Macs if required on some crypto policies" - block: - - name: "PRELIM | Optional | Add Override file Ciphers/Keys/Macs if required on some crypto policies" - ansible.builtin.template: - src: crypto_policy_RSA.j2 - dest: /etc/crypto-policies/policies/modules/RSA-2048 - mode: '0440' - owner: root - group: root - register: rhel8cis_crypto_override_added - - - name: "PRELIM | Optional | Add fact to append crypto_update_command" - ansible.builtin.set_fact: - rhel8cis_crypto_override: true - when: rhel8cis_crypto_override_added is defined - when: - - rhel8cis_optional_crypto_module - - rhel8cis_crypto_policy == 'FIPS' or rhel8cis_crypto_policy == 'FUTURE' - - rhel8cis_rule_1_10 + ansible.builtin.lineinfile: + path: /etc/audit/auditd.conf + regexp: "^{{ item }}( |=)" + line: "{{ item }} = {{ rhel8cis_auditd_extra_conf[item] }}" + notify: Restart_auditd + loop: "{{ rhel8cis_auditd_extra_conf.keys() }}" diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index 01fbdc78..afb4fd76 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -1,8 +1,18 @@ --- -- name: "1.1.1.1 | PATCH | Ensure mounting of cramfs filesystems is disabled" +- name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available" + when: + - rhel8cis_rule_1_1_1_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.1.1.1 + - NIST800-53R5_CM-7 + - cramfs block: - - name: "1.1.1.1 | PATCH | Ensure mounting of cramfs filesystems is disabled | Edit modprobe config" + - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | Edit modprobe config" ansible.builtin.lineinfile: path: /etc/modprobe.d/CIS.conf regexp: "^(#)?install cramfs(\\s|$)" @@ -10,94 +20,262 @@ create: true mode: 0600 - - name: "1.1.1.1 | PATCH | Ensure mounting of cramfs filesystems is disabled | blacklist" + - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | blacklist" ansible.builtin.lineinfile: path: /etc/modprobe.d/blacklist.conf regexp: "^(#)?blacklist cramfs(\\s|$)" line: "blacklist cramfs" create: true - mode: 0600 + mode: '0600' - - name: "1.1.1.1 | PATCH | Ensure mounting of cramfs filesystems is disabled | Disable cramfs" + - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | Disable cramfs" + when: + - not system_is_container community.general.modprobe: name: cramfs state: absent + +- name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available" + when: + - rhel8cis_rule_1_1_1_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.1.1.2 + - NIST800-53R5_CM-7 + - freevxfs + block: + - name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install freevxfs(\\s|$)" + line: "install freevxfs /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist freevxfs(\\s|$)" + line: "blacklist freevxfs" + create: true + mode: '0600' + + - name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | Disable freevxfs" + community.general.modprobe: + name: freevxfs + state: absent when: - not system_is_container + +- name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available" when: - - rhel8cis_rule_1_1_1_1 + - rhel8cis_rule_1_1_1_3 tags: - level1-server - level1-workstation - automated - patch - - rule_1.1.1.1 - - cramfs + - rule_1.1.1.3 + - NIST800-53R5_CM-7 + - hfs + block: + - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install hfs(\\s|$)" + line: "install hfs /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist hfs(\\s|$)" + line: "blacklist hfs" + create: true + mode: '0600' + + - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | Disable squashfs" + when: + - not system_is_container + community.general.modprobe: + name: squashfs + state: absent + +- name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available" + when: + - rhel8cis_rule_1_1_1_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.1.1.4 + - NIST800-53R5_CM-7 + - hfsplus + block: + - name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install hfsplus(\\s|$)" + line: "install hfsplus /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist hfsplus(\\s|$)" + line: "blacklist hfsplus" + create: true + mode: '0600' + + - name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | Disable hfsplus" + when: + - not system_is_container + community.general.modprobe: + name: hfsplus + state: absent + +- name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available" + when: + - rhel8cis_rule_1_1_1_5 + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.1.1.5 + - NIST800-53R5_CM-7 + - jffs2 + block: + - name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install jffs2(\\s|$)" + line: "install jffs2 /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist jffs2(\\s|$)" + line: "blacklist jffs2" + create: true + mode: '0600' -- name: "1.1.1.2 | PATCH | Ensure mounting of squashfs filesystems is disabled" + - name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | Disable jffs2" + when: + - not system_is_container + community.general.modprobe: + name: jffs2 + state: absent + +- name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available" + when: + - rhel8cis_rule_1_1_1_6 + tags: + - level2-server + - level2-workstation + - automated + - patch + - rule_1.1.1.6 + - NIST800-53R5_CM-7 + - squashfs block: - - name: "1.1.1.2 | PATCH | Ensure mounting of squashfs filesystems is disabled | Edit modprobe config" + - name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | Edit modprobe config" ansible.builtin.lineinfile: path: /etc/modprobe.d/CIS.conf regexp: "^(#)?install squashfs(\\s|$)" line: "install squashfs /bin/true" create: true - mode: 0600 + mode: '0600' - - name: "1.1.1.2 | PATCH | Ensure mounting of squashfs filesystems is disabled | blacklist" + - name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | blacklist" ansible.builtin.lineinfile: path: /etc/modprobe.d/blacklist.conf regexp: "^(#)?blacklist squashfs(\\s|$)" line: "blacklist squashfs" create: true - mode: 0600 + mode: '0600' - - name: "1.1.1.2 | PATCH | Ensure mounting of squashfs filesystems is disabled | Disable squashfs" + - name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | Disable squashfs" + when: + - not system_is_container community.general.modprobe: name: squashfs state: absent - when: - - not system_is_container + +- name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available" when: - - rhel8cis_rule_1_1_1_2 + - rhel8cis_rule_1_1_1_7 tags: - level2-server - level2-workstation - automated - patch - - rule_1.1.1.2 - - squashfs - -- name: "1.1.1.3 | PATCH | Ensure mounting of udf filesystems is disabled" + - rule_1.1.1.7 + - NIST800-53R5_CM-7 + - udf block: - - name: "1.1.1.3 | PATCH | Ensure mounting of udf filesystems is disable | Edit modprobe config" + - name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | Edit modprobe config" ansible.builtin.lineinfile: path: /etc/modprobe.d/CIS.conf regexp: "^(#)?install udf(\\s|$)" line: "install udf /bin/true" create: true - mode: 0600 + mode: '0600' - - name: "1.1.1.3 | PATCH | Ensure mounting of udf filesystems is disabled | blacklist" + - name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | blacklist" ansible.builtin.lineinfile: path: /etc/modprobe.d/blacklist.conf regexp: "^(#)?blacklist udf(\\s|$)" line: "blacklist udf" create: true - mode: 0600 + mode: '0600' - - name: "1.1.1.3 | PATCH | Ensure mounting of udf filesystems is disable | Disable udf" + - name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | Disable udf" + when: + - not system_is_container community.general.modprobe: name: udf state: absent - when: - - not system_is_container + +- name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available" when: - - rhel8cis_rule_1_1_1_3 + - rhel8cis_rule_1_1_1_8 tags: - - level2-server + - level1-server - level2-workstation - automated - patch - - rule_1.1.1.3 - - udf + - rule_1.1.1.8 + - NIST800-53R5_SI-3 + - usb + block: + - name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install usb-storage(\\s|$)" + line: "install usb-storage /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist usb-storage(\\s|$)" + line: "blacklist usb-storage" + create: true + mode: '0600' + + - name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | Disable usb" + when: + - not system_is_container + community.general.modprobe: + name: usb-storage + state: absent diff --git a/tasks/section_1/cis_1.1.2.1.x.yml b/tasks/section_1/cis_1.1.2.1.x.yml new file mode 100644 index 00000000..ac5ef2b4 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.1.x.yml @@ -0,0 +1,90 @@ +--- + +- name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition" + when: + - rhel8cis_rule_1_1_2_1_1 + - "'/tmp' not in mount_names" + tags: + - level1-server + - level1-workstation + - automated + - audit + - mounts + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.1.2.1.1 + vars: + warn_control_id: '1.1.2.1.1' + required_mount: '/tmp' + block: + - name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +# via fstab +- name: | + "1.1.2.1.2 | PATCH | Ensure nodev option set on /tmp partition" + "1.1.2.1.3 | PATCH | Ensure nosuid option set on /tmp partition" + "1.1.2.1.4 | PATCH | Ensure noexec option set on /tmp partition" + when: + - item.mount == "/tmp" + - not rhel8cis_tmp_svc + - rhel8cis_rule_1_1_2_1_2 or + rhel8cis_rule_1_1_2_1_3 or + rhel8cis_rule_1_1_2_1_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - mounts + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.1.2.1.2 + - rule_1.1.2.1.3 + - rule_1.1.2.1.4 + ansible.posix.mount: + name: /tmp + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel8cis_rule_1_1_2_1_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_1_3 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_2_1_4 %}noexec{% endif %} + notify: Remount_tmp + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + +# via systemd +- name: | + "1.1.2.1.1 | PATCH | Ensure /tmp is configured" + "1.1.2.1.2 | PATCH | Ensure nodev option set on /tmp partition" + "1.1.2.1.3 | PATCH | Ensure nosuid option set on /tmp partition" + "1.1.2.1.4 | PATCH | Ensure noexec option set on /tmp partition" + when: + - rhel8cis_tmp_svc + - rhel8cis_rule_1_1_2_1_1 or + rhel8cis_rule_1_1_2_1_2 or + rhel8cis_rule_1_1_2_1_3 or + rhel8cis_rule_1_1_2_1_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.1.2.1.1 + - rule_1.1.2.1.2 + - rule_1.1.2.1.3 + - rule_1.1.2.1.4 + notify: Systemd_restart_tmp.mount + ansible.builtin.template: + src: etc/systemd/system/tmp.mount.j2 + dest: /etc/systemd/system/tmp.mount + owner: root + group: root + mode: '0644' diff --git a/tasks/section_1/cis_1.1.2.2.x.yml b/tasks/section_1/cis_1.1.2.2.x.yml new file mode 100644 index 00000000..48efae6d --- /dev/null +++ b/tasks/section_1/cis_1.1.2.2.x.yml @@ -0,0 +1,56 @@ +--- + +- name: "1.1.2.2.1 | PATCH | Ensure /dev/shm is a separate partition" + when: + - rhel8cis_rule_1_1_2_2_1 + - "'/tmp' not in mount_names" + tags: + - level1-server + - level1-workstation + - automated + - audit + - mounts + - NIST800-53R5_CM-7 + - rule_1.1.2.2.1 + vars: + warn_control_id: '1.1.2.2.1' + required_mount: '/dev/shm' + block: + + - name: "1.1.2.2.1 | PATCH | Ensure /dev/shm is a separate partition | Absent" + when: rhel8cis_dev_shm_present is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.2.1 | PATCH | Ensure /dev/shm is a separate partition | Present" + when: rhel8cis_dev_shm_present is undefined + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: | + "1.1.2.2.2 | PATCH | Ensure nodev option set on /dev/shm partition + 1.1.2.2.3 | PATCH | Ensure nosuid option set on /dev/shm partition + 1.1.2.2.4 | PATCH | Ensure noexec option set on /dev/shm partition" + when: + - rhel8cis_dev_shm_present is defined + - rhel8cis_rule_1_1_2_2_2 or + rhel8cis_rule_1_1_2_2_3 or + rhel8cis_rule_1_1_2_2_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - mounts + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.1.2.2.1 + - rule_1.1.2.2.2 + - rule_1.1.2.2.3 + notify: Change_requires_reboot + ansible.posix.mount: + name: /dev/shm + src: tmpfs + fstype: tmpfs + state: mounted + opts: defaults,{% if rhel8cis_rule_1_1_2_2_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_2_3 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_2_2_4 %}noexec{% endif %} diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml new file mode 100644 index 00000000..2d28f9a8 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -0,0 +1,57 @@ +--- + +- name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home" + when: + - rhel8cis_rule_1_1_2_3_1 + - "'/home' not in mount_names" + tags: + - level2-server + - level2-workstation + - automated + - audit + - mounts + - rule_1.1.2.3.1 + - NIST800-53R5_CM-7 + - skip_ansible_lint + vars: + warn_control_id: '1.1.2.3.1' + required_mount: '/home' + block: + - name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home | Warn if partition is absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + register: home_mount_absent + changed_when: home_mount_absent.skipped is undefined + + - name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home | Present" + ansible.builtin.import_tasks: warning_facts.yml + +# skips if mount is absent +- name: | + "1.1.2.3.2 | PATCH | Ensure nodev option set on /home partition + 1.1.2.3.3 | PATCH | Ensure nosuid option set on /home partition + when: + - "'/home' in mount_names" + - item.mount == "/home" + - rhel8cis_rule_1_1_2_3_2 or + rhel8cis_rule_1_1_2_3_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - mounts + - rule_1.1.2.3.2 + - rule_1.1.2.3.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + notify: Change_requires_reboot + ansible.posix.mount: + name: /home + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel8cis_rule_1_1_2_3_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_3_3 %}nosuid{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml new file mode 100644 index 00000000..384a64df --- /dev/null +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -0,0 +1,58 @@ +--- + +- name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var" + block: + - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Warn if partition is absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + register: var_mount_absent + changed_when: var_mount_absent.skipped is undefined + + - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + vars: + warn_control_id: '1.1.2.4.1' + required_mount: '/var' + when: + - "'/var' not in mount_names" + - rhel8cis_rule_1_1_2_4_1 + tags: + - level2-server + - level2-workstation + - automated + - patch + - mounts + - NIST800-53R5_CM-7 + - rule_1.1.2.4.1 + +# skips if mount is absent +- name: | + "1.1.2.4.2 | PATCH | Ensure nodev option set on /var partition" + "1.1.2.4.3 | PATCH | Ensure nosuid option set on /var partition" + when: + - "'/var' in mount_names" + - item.mount == "/var" + - rhel8cis_rule_1_1_2_4_2 or + rhel8cis_rule_1_1_2_4_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - mounts + - skip_ansible_lint + - rule_1.1.2.4.2 + - rule_1.1.2.4.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + notify: Change_requires_reboot + ansible.posix.mount: + name: /var + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel8cis_rule_1_1_2_4_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_4_3 %}nosuid{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" diff --git a/tasks/section_1/cis_1.1.2.5.x.yml b/tasks/section_1/cis_1.1.2.5.x.yml new file mode 100644 index 00000000..c0332eaa --- /dev/null +++ b/tasks/section_1/cis_1.1.2.5.x.yml @@ -0,0 +1,62 @@ +--- + +# Skips if mount is absent +- name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp" + when: + - rhel8cis_rule_1_1_2_5_1 + - "'/var/tmp' not in mount_names" + tags: + - level2-server + - level2-workstation + - automated + - audit + - mounts + - NIST800-53R5_CM-7 + - rule_1.1.2.5.1 + vars: + warn_control_id: '1.1.2.5.1' + required_mount: '/var/tmp' + block: + - name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp | Warn if partition is absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + register: var_tmp_mount_absent + changed_when: var_tmp_mount_absent.skipped is undefined + + - name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +# skips if mount is absent +- name: | + "1.1.2.5.2 | PATCH | Ensure nodev option set on /var/tmp partition" + "1.1.2.5.3 | PATCH | Ensure nosuid option set on /var/tmp partition" + "1.1.2.5.4 | PATCH | Ensure noexec option set on /var/tmp partition" + when: + - "'/var/tmp' in mount_names" + - item.mount == "/var/tmp" + - rhel8cis_rule_1_1_2_5_2 or + rhel8cis_rule_1_1_2_5_3 or + rhel8cis_rule_1_1_2_5_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - mounts + - skip_ansible_lint + - rule_1.1.2.5.2 + - rule_1.1.2.5.3 + - rule_1.1.2.5.4 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + notify: Change_requires_reboot + ansible.posix.mount: + name: /var/tmp + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel8cis_rule_1_1_2_5_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_5_3 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_2_5_4 %}noexec{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" diff --git a/tasks/section_1/cis_1.1.2.6.x.yml b/tasks/section_1/cis_1.1.2.6.x.yml new file mode 100644 index 00000000..ce9f79e7 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -0,0 +1,61 @@ +--- + +- name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log" + when: + - rhel8cis_rule_1_1_2_6_1 + - "'/var/log' not in mount_names" + tags: + - level2-server + - level2-workstation + - automated + - audit + - mounts + - rule_1.1.2.6.1 + - NIST800-53R5_CM-7 + vars: + warn_control_id: '1.1.2.6.1' + required_mount: '/var/log' + block: + - name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log | Warn if partition is absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + register: var_log_mount_absent + changed_when: var_log_mount_absent.skipped is undefined + + - name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +# skips if mount is absent +- name: | + "1.1.2.6.2 | PATCH | Ensure nodev option set on /var/log partition" + "1.1.2.6.3 | PATCH | Ensure nosuid option set on /var/log partition" + "1.1.2.6.4 | PATCH | Ensure noexec option set on /var/log partition" + when: + - "'/var/log' in mount_names" + - item.mount == "/var/log" + - rhel8cis_rule_1_1_2_6_2 or + rhel8cis_rule_1_1_2_6_3 or + rhel8cis_rule_1_1_2_6_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - mounts + - skip_ansible_lint + - rule_1.1.2.6.2 + - rule_1.1.2.6.3 + - rule_1.1.2.6.4 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + notify: Change_requires_reboot + ansible.posix.mount: + name: /var/log + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel8cis_rule_1_1_2_6_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_6_3 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_2_6_4 %}noexec{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" diff --git a/tasks/section_1/cis_1.1.2.7.x.yml b/tasks/section_1/cis_1.1.2.7.x.yml new file mode 100644 index 00000000..7463e082 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -0,0 +1,60 @@ +--- + +- name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit" + when: + - rhel8cis_rule_1_1_2_7_1 + - "'/var/log/audit' not in mount_names" + tags: + - level2-server + - level2-workstation + - automated + - audit + - mounts + - rule_1.1.2.7.1 + - NIST800-53R5_CM-7 + vars: + warn_control_id: '1.1.2.7.1' + required_mount: '/var/log/audit' + block: + - name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Warn if partition is absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + register: var_log_audit_mount_absent + changed_when: var_log_audit_mount_absent.skipped is undefined + + - name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +# skips if mount is absent +- name: | + "1.1.2.7.2 | PATCH | Ensure nodev option set on /var/log/audit partition" + "1.1.2.7.3 | PATCH | Ensure nosuid option set on /var/log/audit partition" + "1.1.2.7.4 | PATCH | Ensure noexec option set on /var/log/audit partition" + when: + - "'/var/log/audit' in mount_names" + - item.mount == "/var/log/audit" + - rhel8cis_rule_1_1_2_7_2 or + rhel8cis_rule_1_1_2_7_3 or + rhel8cis_rule_1_1_2_7_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - mounts + - rule_1.1.2.7.2 + - rule_1.1.2.7.3 + - rule_1.1.2.7.4 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + notify: Change_requires_reboot + ansible.posix.mount: + name: /var/log/audit + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel8cis_rule_1_1_2_7_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_7_3 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_2_7_4 %}noexec{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" diff --git a/tasks/section_1/cis_1.1.2.x.yml b/tasks/section_1/cis_1.1.2.x.yml deleted file mode 100644 index c77a25a2..00000000 --- a/tasks/section_1/cis_1.1.2.x.yml +++ /dev/null @@ -1,84 +0,0 @@ ---- - -- name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition" - block: - - name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" - - - name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition | Present" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '1.1.2.1' - required_mount: '/tmp' - when: - - rhel8cis_rule_1_1_2_1 - - "'/tmp' not in mount_names" - tags: - - level1-server - - level1-workstation - - automated - - audit - - mounts - - rule_1.1.2.1 - -# via fstab -- name: | - "1.1.2.2 | PATCH | Ensure nodev option set on /tmp partition" - "1.1.2.3 | PATCH | Ensure noexec option set on /tmp partition" - "1.1.2.4 | PATCH | Ensure nosuid option set on /tmp partition" - ansible.posix.mount: - name: /tmp - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel8cis_rule_1_1_2_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_3 %}noexec,{% endif %}{% if rhel8cis_rule_1_1_2_4 %}nosuid{% endif %} - notify: remount tmp - with_items: - - "{{ ansible_mounts }}" - loop_control: - label: "{{ item.device }}" - when: - - item.mount == "/tmp" - - not rhel8cis_tmp_svc - - rhel8cis_rule_1_1_2_2 or - rhel8cis_rule_1_1_2_3 or - rhel8cis_rule_1_1_2_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - mounts - - rule_1.1.2.2 - - rule_1.1.2.3 - - rule_1.1.2.4 - -# via systemd -- name: | - "1.1.2.1 | PATCH | Ensure /tmp is configured" - "1.1.2.2 | PATCH | Ensure nodev option set on /tmp partition" - "1.1.2.3 | PATCH | Ensure noexec option set on /tmp partition" - "1.1.2.4 | PATCH | Ensure nosuid option set on /tmp partition" - ansible.builtin.template: - src: etc/systemd/system/tmp.mount.j2 - dest: /etc/systemd/system/tmp.mount - owner: root - group: root - mode: 0644 - notify: systemd restart tmp.mount - when: - - rhel8cis_tmp_svc - - rhel8cis_rule_1_1_2_1 or - rhel8cis_rule_1_1_2_2 or - rhel8cis_rule_1_1_2_3 or - rhel8cis_rule_1_1_2_4 - tags: - - level1-server - - level1-workstation - - patch - - mounts - - rule_1.1.2.1 - - rule_1.1.2.2 - - rule_1.1.2.3 - - rule_1.1.2.4 diff --git a/tasks/section_1/cis_1.1.3.x.yml b/tasks/section_1/cis_1.1.3.x.yml deleted file mode 100644 index 9a7b7f4f..00000000 --- a/tasks/section_1/cis_1.1.3.x.yml +++ /dev/null @@ -1,59 +0,0 @@ ---- - -- name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var" - block: - - name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var | Warn if partition is absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: var_mount_absent - changed_when: var_mount_absent.skipped is undefined - - - name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var | Present" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '1.1.3.1' - required_mount: '/var' - when: - - "'/var' not in mount_names" - - rhel8cis_rule_1_1_3_1 - tags: - - level2-server - - level2-workstation - - automated - - patch - - mounts - - rule_1.1.3.1 - -# skips if mount is absent -- name: | - "1.1.3.2 | PATCH | Ensure nodev option set on /var partition" - "1.1.3.3 | PATCH | Ensure noexec option set on /var partition" - "1.1.3.4 | PATCH | Ensure nosuid option set on /var partition" - ansible.posix.mount: - name: /var - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel8cis_rule_1_1_3_3 %}noexec,{% endif %}{% if rhel8cis_rule_1_1_3_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_3_4 %}nosuid{% endif %} - notify: change_requires_reboot - with_items: - - "{{ ansible_mounts }}" - loop_control: - label: "{{ item.device }}" - when: - - "'/var' in mount_names" - - item.mount == "/var" - - rhel8cis_rule_1_1_3_1 # This is required so the check takes place - - rhel8cis_rule_1_1_3_2 or - rhel8cis_rule_1_1_3_3 or - rhel8cis_rule_1_1_3_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - mounts - - skip_ansible_lint - - rule_1.1.3.2 - - rule_1.1.3.3 - - rule_1.1.3.4 diff --git a/tasks/section_1/cis_1.1.4.x.yml b/tasks/section_1/cis_1.1.4.x.yml deleted file mode 100644 index 454318f3..00000000 --- a/tasks/section_1/cis_1.1.4.x.yml +++ /dev/null @@ -1,60 +0,0 @@ ---- - -# Skips if mount is absent -- name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp" - block: - - name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp | Warn if partition is absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: var_tmp_mount_absent - changed_when: var_tmp_mount_absent.skipped is undefined - - - name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp | Present" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '1.1.4.1' - required_mount: '/var/tmp' - when: - - rhel8cis_rule_1_1_4_1 - - "'/var/tmp' not in mount_names" - tags: - - level2-server - - level2-workstation - - automated - - audit - - mounts - - rule_1.1.4.1 - -# skips if mount is absent -- name: | - "1.1.4.2 | PATCH | Ensure noexec option set on /var/tmp partition" - "1.1.4.3 | PATCH | Ensure nosuid option set on /var/tmp partition" - "1.1.4.4 | PATCH | Ensure nodev option set on /var/tmp partition" - ansible.posix.mount: - name: /var/tmp - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel8cis_rule_1_1_4_2 %}noexec,{% endif %}{% if rhel8cis_rule_1_1_4_4 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_4_3 %}nosuid{% endif %} - notify: change_requires_reboot - with_items: - - "{{ ansible_mounts }}" - loop_control: - label: "{{ item.device }}" - when: - - "'/var/tmp' in mount_names" - - item.mount == "/var/tmp" - - rhel8cis_rule_1_1_4_1 # This is required so the check takes place - - rhel8cis_rule_1_1_4_2 or - rhel8cis_rule_1_1_4_3 or - rhel8cis_rule_1_1_4_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - mounts - - skip_ansible_lint - - rule_1.1.4.2 - - rule_1.1.4.3 - - rule_1.1.4.4 diff --git a/tasks/section_1/cis_1.1.5.x.yml b/tasks/section_1/cis_1.1.5.x.yml deleted file mode 100644 index 2614cc1e..00000000 --- a/tasks/section_1/cis_1.1.5.x.yml +++ /dev/null @@ -1,61 +0,0 @@ ---- - -- name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log" - block: - - name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log | Warn if partition is absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: var_log_mount_absent - changed_when: var_log_mount_absent.skipped is undefined - - - name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log | Present" - ansible.builtin.import_tasks: warning_facts.yml - - vars: - warn_control_id: '1.1.5.1' - required_mount: '/var/log' - when: - - rhel8cis_rule_1_1_5_1 - - "'/var/log' not in mount_names" - tags: - - level2-server - - level2-workstation - - automated - - audit - - mounts - - rule_1.1.5.1 - - skip_ansible_lint - -# skips if mount is absent -- name: | - "1.1.5.2 | PATCH | Ensure nodev option set on /var/log partition" - "1.1.5.3 | PATCH | Ensure noexec option set on /var/log partition" - "1.1.5.4 | PATCH | Ensure nosuid option set on /var/log partition" - ansible.posix.mount: - name: /var/log - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel8cis_rule_1_1_5_3 %}noexec,{% endif %}{% if rhel8cis_rule_1_1_5_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_5_4 %}nosuid{% endif %} - notify: change_requires_reboot - with_items: - - "{{ ansible_mounts }}" - loop_control: - label: "{{ item.device }}" - when: - - "'/var/log' in mount_names" - - item.mount == "/var/log" - - rhel8cis_rule_1_1_5_1 # This is required so the check takes place - - rhel8cis_rule_1_1_5_2 or - rhel8cis_rule_1_1_5_3 or - rhel8cis_rule_1_1_5_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - mounts - - skip_ansible_lint - - rule_1.1.5.2 - - rule_1.1.5.3 - - rule_1.1.5.4 diff --git a/tasks/section_1/cis_1.1.6.x.yml b/tasks/section_1/cis_1.1.6.x.yml deleted file mode 100644 index 8cb7fac3..00000000 --- a/tasks/section_1/cis_1.1.6.x.yml +++ /dev/null @@ -1,60 +0,0 @@ ---- - -- name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit" - block: - - name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Warn if partition is absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: var_log_audit_mount_absent - changed_when: var_log_audit_mount_absent.skipped is undefined - - - name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Present" - ansible.builtin.import_tasks: warning_facts.yml - - vars: - warn_control_id: '1.1.6.1' - required_mount: '/var/log/audit' - when: - - rhel8cis_rule_1_1_6_1 - - "'/var/log/audit' not in mount_names" - tags: - - level2-server - - level2-workstation - - automated - - audit - - mounts - - rule_1.1.6.1 - -# skips if mount is absent -- name: | - "1.1.6.2 | PATCH | Ensure noexec option set on /var/log/audit partition" - "1.1.6.3 | PATCH | Ensure nodev option set on /var/log/audit partition" - "1.1.6.4 | PATCH | Ensure nosuid option set on /var/log/audit partition" - ansible.posix.mount: - name: /var/log/audit - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel8cis_rule_1_1_6_2 %}noexec,{% endif %}{% if rhel8cis_rule_1_1_6_3 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_6_4 %}nosuid{% endif %} - notify: change_requires_reboot - with_items: - - "{{ ansible_mounts }}" - loop_control: - label: "{{ item.device }}" - when: - - "'/var/log/audit' in mount_names" - - item.mount == "/var/log/audit" - - rhel8cis_rule_1_1_6_1 # This is required so the check takes place - - rhel8cis_rule_1_1_6_2 or - rhel8cis_rule_1_1_6_3 or - rhel8cis_rule_1_1_6_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - mounts - - skip_ansible_lint - - rule_1.1.6.2 - - rule_1.1.6.3 - - rule_1.1.6.4 diff --git a/tasks/section_1/cis_1.1.7.x.yml b/tasks/section_1/cis_1.1.7.x.yml deleted file mode 100644 index 63d2240d..00000000 --- a/tasks/section_1/cis_1.1.7.x.yml +++ /dev/null @@ -1,63 +0,0 @@ ---- - -- name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home" - block: - - name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home | Warn if partition is absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: home_mount_absent - changed_when: home_mount_absent.skipped is undefined - - - name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home | Present" - ansible.builtin.import_tasks: warning_facts.yml - - vars: - warn_control_id: '1.1.7.1' - required_mount: '/home' - when: - - rhel8cis_rule_1_1_7_1 - - "'/home' not in mount_names" - tags: - - level2-server - - level2-workstation - - automated - - audit - - mounts - - rule_1.1.7.1 - - skip_ansible_lint - -# skips if mount is absent -- name: | - "1.1.7.2 | PATCH | Ensure nodev option set on /home partition - 1.1.7.3 | PATCH | Ensure nosuid option set on /home partition - 1.1.7.4 | PATCH | Ensure usrquota option set on /home partition - 1.1.7.5 | PATCH | Ensure grpquota option set on /home partition" - ansible.posix.mount: - name: /home - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel8cis_rule_1_1_7_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_7_3 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_7_4 %}usrquota,{% endif %}{% if rhel8cis_rule_1_1_7_5 %}grpquota{% endif %} - notify: change_requires_reboot - with_items: - - "{{ ansible_mounts }}" - loop_control: - label: "{{ item.device }}" - when: - - "'/home' in mount_names" - - item.mount == "/home" - - rhel8cis_rule_1_1_7_1 - - rhel8cis_rule_1_1_7_2 or - rhel8cis_rule_1_1_7_3 or - rhel8cis_rule_1_1_7_4 or - rhel8cis_rule_1_1_7_5 - tags: - - level1-server - - level1-workstation - - automated - - patch - - mounts - - rule_1.1.7.2 - - rule_1.1.7.3 - - rule_1.1.7.4 - - skip_ansible_lint diff --git a/tasks/section_1/cis_1.1.8.x.yml b/tasks/section_1/cis_1.1.8.x.yml deleted file mode 100644 index 4bdbd8f5..00000000 --- a/tasks/section_1/cis_1.1.8.x.yml +++ /dev/null @@ -1,43 +0,0 @@ ---- - -# Skips if mount is absent -- name: | - "1.1.8.1 | PATCH | Ensure nodev option set on /dev/shm partition - 1.1.8.2 | PATCH | Ensure nosuid option set on /dev/shm partition - 1.1.8.3 | PATCH | Ensure noexec option set on /dev/shm partition" - block: - - name: | - "1.1.8.1 | AUDIT | Ensure nodev option set on /dev/shm partition | Check for /dev/shm existence - 1.1.8.2 | AUDIT | Ensure nosuid option set on /dev/shm partition | Check for /dev/shm existence - 1.1.8.3 | AUDIT | Ensure noexec option set on /dev/shm partition | Check for /dev/shm existence" - ansible.builtin.shell: mount -l | grep -E '\s/dev/shm\s' - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_1_1_8_x_dev_shm_status - - - name: | - "1.1.8.1 | PATCH | Ensure nodev option set on /dev/shm partition | Set nodev option - 1.1.8.2 | PATCH | Ensure noexec option set on /dev/shm partition | Set nosuid option - 1.1.8.3 | PATCH | Ensure nosuid option set on /dev/shm partition | Set noexec option" - ansible.posix.mount: - name: /dev/shm - src: tmpfs - fstype: tmpfs - state: mounted - opts: defaults,{% if rhel8cis_rule_1_1_8_2 %}noexec,{% endif %}{% if rhel8cis_rule_1_1_8_1 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_8_3 %}nosuid{% endif %} - when: "'dev/shm' in rhel8cis_1_1_8_x_dev_shm_status.stdout" - notify: change_requires_reboot - when: - - rhel8cis_rule_1_1_8_1 or - rhel8cis_rule_1_1_8_2 or - rhel8cis_rule_1_1_8_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - mounts - - rule_1.1.8.1 - - rule_1.1.8.2 - - rule_1.1.8.3 diff --git a/tasks/section_1/cis_1.1.x.yml b/tasks/section_1/cis_1.1.x.yml deleted file mode 100644 index 1131f810..00000000 --- a/tasks/section_1/cis_1.1.x.yml +++ /dev/null @@ -1,53 +0,0 @@ ---- - -- name: "1.1.9 | PATCH | Disable Automounting" - ansible.builtin.service: - name: autofs - enabled: false - when: - - not rhel8cis_allow_autofs - - "'autofs' in ansible_facts.packages" - - rhel8cis_rule_1_1_9 - tags: - - level1-server - - level2-workstation - - automated - - patch - - mounts - - automounting - - rule_1.1.9 - -- name: "1.1.10 | PATCH | Disable USB Storage" - block: - - name: "1.1.10 | PATCH | Disable USB Storage | Edit modprobe config" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/CIS.conf - regexp: "^(#)?install usb-storage(\\s|$)" - line: "install usb-storage /bin/true" - create: true - owner: root - group: root - mode: 0600 - - - name: "1.1.10 | PATCH | Disable USB Storage | | blacklist" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/blacklist.conf - regexp: "^(#)?blacklist usb-storage(\\s|$)" - line: "blacklist usb-storage" - create: true - mode: 0600 - - - name: "1.1.10 | PATCH | Disable USB Storage | Edit modprobe config" - community.general.modprobe: - name: usb-storage - state: absent - when: - - rhel8cis_rule_1_1_10 - tags: - - level1-server - - level2-workstation - - automated - - patch - - mounts - - removable_storage - - rule_1.1.10 diff --git a/tasks/section_1/cis_1.10.yml b/tasks/section_1/cis_1.10.yml deleted file mode 100644 index 765b5241..00000000 --- a/tasks/section_1/cis_1.10.yml +++ /dev/null @@ -1,24 +0,0 @@ ---- - -- name: "1.10 | PATCH | Ensure system-wide crypto policy is not legacy" - block: - - name: "1.10 | PATCH | Ensure system-wide crypto policy is not legacy | set_fact" - ansible.builtin.set_fact: - rhel8cis_full_crypto_policy: "{{ rhel8cis_crypto_policy }}{% if rhel8cis_crypto_policy_module | length > 0 %}:{{ rhel8cis_crypto_policy_module }}{% endif %}" - - - name: "1.10 | PATCH | Ensure system-wide crypto policy is not legacy" - ansible.builtin.shell: | - update-crypto-policies --set "{{ rhel8cis_full_crypto_policy }}{% if rhel8cis_crypto_override %}:RSA-2048{% endif %}" - update-crypto-policies - notify: change_requires_reboot - when: - - rhel8cis_system_wide_crypto_policy.stdout != rhel8cis_full_crypto_policy - when: - - rhel8cis_rule_1_10 - tags: - - level1-server - - level1-workstation - - automated - - no system_is_ec2 - - patch - - rule_1.10 diff --git a/tasks/section_1/cis_1.2.x.yml b/tasks/section_1/cis_1.2.x.yml index d43e4b03..6c2cf944 100644 --- a/tasks/section_1/cis_1.2.x.yml +++ b/tasks/section_1/cis_1.2.x.yml @@ -1,68 +1,101 @@ --- -- name: "1.2.1 | PATCH | Ensure Red Hat Subscription Manager connection is configured" - community.general.redhat_subscription: - state: present - username: "{{ rhel8cis_rh_sub_user }}" - password: "{{ rhel8cis_rh_sub_password }}" - auto_attach: true - no_log: true +- name: "1.2.1 | AUDIT | Ensure GPG keys are configured" when: - - ansible_distribution == "RedHat" - - rhel8cis_rhnsd_required - rhel8cis_rule_1_2_1 + - ansible_distribution == "RedHat" or + ansible_distribution == "Rocky" or + ansible_distribution == "AlmaLinux" or + ansible_distribution == "Oracle Linux" tags: - level1-server - level1-workstation - manual - patch + - NIST800-53R5_SI-2 - rule_1.2.1 - - skip_ansible_lint # Added as no_log still errors on ansible-lint -- name: "1.2.2 | AUDIT | Ensure GPG keys are configured" ansible.builtin.shell: "PKG=`rpm -qf {{ rpm_gpg_key }}` && rpm -q --queryformat \"%{PACKAGER} %{SIGPGP:pgpsig}\\n\" \"${PKG}\" | grep \"^{{ rpm_packager }}.*Key.ID.{{ rpm_key }}\"" changed_when: false + +- name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated" when: - rhel8cis_rule_1_2_2 - - ansible_distribution == "RedHat" or - ansible_distribution == "Rocky" or - ansible_distribution == "AlmaLinux" or - ansible_distribution == "OracleLinux" tags: - level1-server - level1-workstation - - manual + - automated - patch + - NIST800-53R5_SI-2 - rule_1.2.2 - -- name: "1.2.3 | PATCH | Ensure gpgcheck is globally activated" block: - - name: "1.2.3 | AUDIT | Ensure gpgcheck is globally activated | Find repos" + - name: "1.2.2 | AUDIT | Ensure gpgcheck is globally activated | Find repos" ansible.builtin.find: paths: /etc/yum.repos.d patterns: "*.repo" register: yum_repos changed_when: false - - name: "1.2.3 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos" + - name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos" ansible.builtin.replace: name: "{{ item.path }}" regexp: "^gpgcheck=0" replace: "gpgcheck=1" - with_items: - - "{{ yum_repos.files }}" + loop: "{{ yum_repos.files }}" loop_control: label: "{{ item.path }}" + + - name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated | Update dnf.conf" + ansible.builtin.lineinfile: + path: /etc/dnf/dnf.conf + regexp: ^(#|)gpgcheck= + line: gpgcheck=1 + +- name: "1.2.3 | PATCH | Ensure repo_gpgcheck is globally activated" when: - rhel8cis_rule_1_2_3 tags: - - level1-server - - level1-workstation + - level2-server + - level2-workstation - automated - patch + - NIST800-53R5_SI-2 - rule_1.2.3 + block: + - name: "1.2.3 | AUDIT | Ensure repo_gpgcheck is globally activated | Find repos" + ansible.builtin.find: + paths: /etc/yum.repos.d + patterns: "*.repo" + register: yum_repos + changed_when: false + + - name: "1.2.3 | PATCH | Ensure repo_gpgcheck is globally activated | Update yum.repos" + ansible.builtin.replace: + name: "{{ item.path }}" + regexp: "^repo_gpgcheck=0" + replace: "repo_gpgcheck=1" + loop: "{{ yum_repos.files }}" + loop_control: + label: "{{ item.path }}" + + - name: "1.2.3 | PATCH | Ensure repo_gpgcheck is globally activated | Update dnf.conf" + ansible.builtin.lineinfile: + path: /etc/dnf/dnf.conf + regexp: ^(#|)repo_gpgcheck= + line: repo_gpgcheck=1 - name: "1.2.4 | AUDIT | Ensure package manager repositories are configured" + when: + - rhel8cis_rule_1_2_4 + tags: + - level1-server + - level1-workstation + - manual + - audit + - NIST800-53R5_SI-2 + - rule_1.2.4 + vars: + warn_control_id: '1.2.4' block: - name: "1.2.4 | AUDIT | Ensure package manager repositories are configured | Get repo list" ansible.builtin.shell: dnf repolist @@ -78,15 +111,42 @@ - "{{ dnf_configured.stdout_lines }}" - name: "1.2.4 | AUDIT | Ensure package manager repositories are configured | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '1.2.4' + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "1.2.5 | PATCH | Ensure updates, patches, and additional security software are installed" when: - - rhel8cis_rule_1_2_4 + - rhel8cis_rule_1_2_5 + - not system_is_ec2 tags: - level1-server - level1-workstation - - manual - - audit - - rule_1.2.4 - - skip_ansible_lint + - automated + - patch + - rule_1.2_5 + notify: Change_requires_reboot + block: + - name: "1.2.5 | PATCH | Ensure updates, patches, and additional security software are installed | Patch" + ansible.builtin.package: + name: "*" + state: latest + + - name: "1.2.5 | PATCH | Ensure updates, patches, and additional security software are installed | update_facts" + ansible.builtin.package_facts: + manager: auto + +- name: "1.2.5 | PATCH | Ensure updates, patches, and additional security software are installed | limit kernels" + when: + - rhel8cis_rule_1_2_5 + - rhel8cis_apply_installed_kernel_limit + tags: + - level1-server + - level1-workstation + - automated + - patch + - kernel_limit + - rule_1.2.5 + ansible.builtin.lineinfile: + path: /etc/dnf/dnf.conf + regexp: ^installonly_limit= + line: installonly_limit={{ rhel8cis_installed_kernel_limit }} diff --git a/tasks/section_1/cis_1.3.x.yml b/tasks/section_1/cis_1.3.x.yml index a3916384..95f383e9 100644 --- a/tasks/section_1/cis_1.3.x.yml +++ b/tasks/section_1/cis_1.3.x.yml @@ -1,51 +1,71 @@ --- -- name: "1.3.1 | PATCH | Ensure AIDE is installed" - block: - - name: "1.3.1 | PATCH | Ensure AIDE is installed | Install AIDE" - ansible.builtin.package: - name: aide - state: present - - - name: "1.3.1 | PATCH | Ensure AIDE is installed | Configure AIDE" - ansible.builtin.shell: /usr/sbin/aide --init -B 'database_out=file:/var/lib/aide/aide.db.gz' - changed_when: false - failed_when: false - async: 45 - poll: 0 - args: - creates: /var/lib/aide/aide.db.gz - when: not ansible_check_mode +- name: "1.3.1 | PATCH | Ensure bootloader password is set" + ansible.builtin.copy: + dest: "{{ rhel8cis_boot_path }}user.cfg" # noqa template-instead-of-copy + content: "GRUB2_PASSWORD={{ rhel8cis_bootloader_password_hash }}" + owner: root + group: root + mode: '0600' + notify: Rebuild_grub when: - - rhel8cis_config_aide + - rhel8cis_set_boot_pass - rhel8cis_rule_1_3_1 tags: - level1-server - level1-workstation - automated - - aide + - grub - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_1.3.1 -- name: "1.3.2 | PATCH | Ensure filesystem integrity is regularly checked" - ansible.builtin.cron: - name: Run AIDE integrity check - cron_file: "{{ rhel8cis_aide_cron['cron_file'] }}" - user: "{{ rhel8cis_aide_cron['cron_user'] }}" - minute: "{{ rhel8cis_aide_cron['aide_minute'] | default('0') }}" - hour: "{{ rhel8cis_aide_cron['aide_hour'] | default('5') }}" - day: "{{ rhel8cis_aide_cron['aide_day'] | default('*') }}" - month: "{{ rhel8cis_aide_cron['aide_month'] | default('*') }}" - weekday: "{{ rhel8cis_aide_cron['aide_weekday'] | default('*') }}" - job: "{{ rhel8cis_aide_cron['aide_job'] }}" +- name: "1.3.2 | PATCH | Ensure permissions on bootloader config are configured" when: - rhel8cis_rule_1_3_2 - - not system_is_ec2 + - grub_cfg.stat.exists + - grub_cfg.stat.islnk tags: - level1-server - level1-workstation - automated - - aide - - file_integrity + - grub - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_1.3.2 + block: + - name: "1.3.2 | PATCH | Ensure permissions on bootloader config are configured | BIOS" + when: rhel8cis_legacy_boot + ansible.builtin.file: + path: "{{ rhel8cis_boot_path }}" + owner: root + group: root + mode: '0600' + recurse: true + + - name: "1.3.2 | PATCH | Ensure permissions on bootloader config are configured | EFI" + when: not rhel8cis_legacy_boot + ansible.builtin.file: + path: "{{ rhel8cis_boot_path }}" + owner: root + group: root + mode: '0700' + recurse: true + + - name: "1.3.2 | PATCH | Ensure permissions on bootloader config are configured | UEFI" + when: + - not rhel8cis_legacy_boot + - item.mount == "/boot/efi" + notify: Change_requires_reboot + ansible.posix.mount: + name: /boot/efi + src: "UUID={{ item.uuid }}" + fstype: vfat + state: present + opts: defaults,umask=0027,fmask=0077,uid=0,gid=0 + passno: '0' + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.mount }}" diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index 5a2c487e..631aac39 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -1,74 +1,71 @@ --- -- name: "1.4.1 | PATCH | Ensure bootloader password is set" - ansible.builtin.copy: - dest: /boot/grub2/user.cfg # noqa template-instead-of-copy - content: "GRUB2_PASSWORD={{ rhel8cis_bootloader_password_hash }}" - owner: root - group: root - mode: 0600 - notify: rhel8cis_grub2cfg +- name: "1.4.1 | PATCH | Ensure address space layout randomization (ASLR) is enabled" when: - - rhel8cis_set_boot_pass - rhel8cis_rule_1_4_1 tags: - level1-server - level1-workstation - automated - - grub - patch + - sysctl + - NIST800-53R5_CM-6 - rule_1.4.1 + ansible.posix.sysctl: + name: kernel.randomize_va_space + value: '2' + reload: true + sysctl_file: /etc/sysctl.d/60-kernel_sysctl.conf + sysctl_set: true + ignoreerrors: true -- name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured" - block: - - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured" - ansible.builtin.file: - path: "{{ grub_cfg.stat.lnk_source }}" - owner: root - group: root - mode: 0600 - - - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | UEFI" - ansible.posix.mount: - name: /boot/efi - src: "UUID={{ item.uuid }}" - fstype: vfat - state: present - opts: defaults,umask=0027,fmask=0077,uid=0,gid=0 - passno: '0' - with_items: - - "{{ ansible_mounts }}" - loop_control: - label: "{{ item.mount }}" - when: - - not rhel8cis_legacy_boot - - item.mount == "/boot/efi" +- name: "1.4.2 | PATCH | Ensure ptrace_scope is restricted" when: - rhel8cis_rule_1_4_2 - - grub_cfg.stat.exists - - grub_cfg.stat.islnk tags: - level1-server - level1-workstation - automated - - grub - patch + - sysctl + - NIST800-53R5_CM-6 - rule_1.4.2 + ansible.posix.sysctl: + name: kernel.yama.ptrace_scope + value: '1' + reload: true + sysctl_file: /etc/sysctl.d/60-kernel_sysctl.conf + sysctl_set: true + ignoreerrors: true -- name: "1.4.3 | PATCH | Ensure authentication is required when booting into rescue mode" +- name: "1.4.3 | PATCH | Ensure core dump backtraces are disabled" + tags: + - level1-server + - level1-workstation + - automated + - patch + - sysctl + - NIST800-53R5_CM-6 + - rule_1.4.3 ansible.builtin.lineinfile: - path: /etc/systemd/system/rescue.service.d/00-require-auth.conf - regexp: '^ExecStart=' - line: "ExecStart=-/usr/lib/systemd/systemd-sulogin-shell rescue" - create: true - owner: root - group: root - mode: 0644 + path: /etc/systemd/coredump.conf + regexp: 'ProcessSizeMax=' + line: 'ProcessSizeMax=0' when: - rhel8cis_rule_1_4_3 + +- name: "1.4.4 | PATCH | Ensure core dump storage is disabled" + when: + - rhel8cis_rule_1_4_4 + - systemd_coredump.stat.exists tags: - level1-server - level1-workstation - automated - patch - - rule_1.4.3 + - rule_1.4.4 + notify: Systemd_daemon_reload + ansible.builtin.lineinfile: + path: /etc/systemd/coredump.conf + regexp: 'Storage=' + line: 'Storage=none' diff --git a/tasks/section_1/cis_1.5.1.x.yml b/tasks/section_1/cis_1.5.1.x.yml new file mode 100644 index 00000000..7b229530 --- /dev/null +++ b/tasks/section_1/cis_1.5.1.x.yml @@ -0,0 +1,154 @@ +--- + +- name: "1.5.1.1 | PATCH | Ensure SELinux is installed" + when: + - rhel8cis_rule_1_5_1_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.1 + ansible.builtin.package: + name: libselinux + state: present + +- name: "1.5.1.2 | PATCH | Ensure SELinux is not disabled in bootloader configuration" + when: + - rhel8cis_rule_1_5_1_2 + tags: + - level1-server + - level1-workstation + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.2 + notify: Rebuild_grub + ansible.builtin.replace: + path: /etc/default/grub + regexp: '(selinux|enforcing)\s*=\s*0\s*' + replace: '' + register: selinux_grub_patch + ignore_errors: true # noqa ignore-errors + +# State set to enforcing because control 1.5.1.5 requires enforcing to be set +- name: "1.5.1.3 | PATCH | Ensure SELinux policy is configured" + when: + - rhel8cis_rule_1_5_1_3 + tags: + - level1-server + - level1-workstation + - automated + - selinux + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.3 + notify: Change_requires_reboot + ansible.posix.selinux: + conf: /etc/selinux/config + policy: "{{ rhel8cis_selinux_policy }}" + state: "{{ rhel8cis_selinux_state }}" + +# State set to enforcing because control 1.6.1.5 requires enforcing to be set +- name: "1.5.1.4 | PATCH | Ensure the SELinux mode is not disabled" + when: + - rhel8cis_rule_1_5_1_4 + tags: + - level1-server + - level1-workstation + - auotmated + - selinux + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.4 + ansible.posix.selinux: + conf: /etc/selinux/config + policy: "{{ rhel8cis_selinux_policy }}" + state: "{{ rhel8cis_selinux_state }}" + +- name: "1.5.1.5 | PATCH | Ensure the SELinux state is enforcing" + when: + - rhel8cis_rule_1_5_1_5 + tags: + - level2-server + - level2-workstation + - automated + - selinux + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.5 + ansible.posix.selinux: + conf: /etc/selinux/config + policy: "{{ rhel8cis_selinux_policy }}" + state: enforcing + +- name: "1.5.1.6 | AUDIT | Ensure no unconfined services exist" + when: + - rhel8cis_rule_1_5_1_6 + tags: + - level1-server + - level1-workstation + - automated + - audit + - services + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.6 + vars: + warn_control_id: '1.5.1.6' + block: + - name: "1.5.1.6 | AUDIT | Ensure no unconfined services exist | Find the unconfined services" + ansible.builtin.shell: ps -eZ | grep unconfined_service_t | egrep -vw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }' + register: rhel8cis_1_5_1_6_unconf_services + failed_when: false + changed_when: false + + - name: "1.5.1.6 | WARN | Ensure no unconfined services exist | Message on unconfined services" + when: + - rhel8cis_1_5_1_6_unconf_services is defined + - rhel8cis_1_5_1_6_unconf_services.stdout | length > 0 + ansible.builtin.debug: + msg: "Warning!! You have unconfined services: {{ rhel8cis_1_5_1_6_unconf_services.stdout_lines }}" + + - name: "1.5.1.6 | WARN | Ensure no unconfined services exist | warning count" + when: + - rhel8cis_1_5_1_6_unconf_services is defined + - rhel8cis_1_5_1_6_unconf_services.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "1.5.1.7 | PATCH | Ensure the MCS Translation Service (mcstrans) is not installed" + when: + - rhel8cis_rule_1_5_1_7 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.7 + ansible.builtin.package: + name: mcstrans + state: absent + +- name: "1.5.1.8 | PATCH | Ensure SETroubleshoot is not installed" + ansible.builtin.package: + name: setroubleshoot + state: absent + when: + - rhel8cis_rule_1_5_1_8 + - "'setroubleshoot' in ansible_facts.packages" + tags: + - level1-server + - automated + - selinux + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.8 diff --git a/tasks/section_1/cis_1.5.x.yml b/tasks/section_1/cis_1.5.x.yml deleted file mode 100644 index f035f682..00000000 --- a/tasks/section_1/cis_1.5.x.yml +++ /dev/null @@ -1,48 +0,0 @@ ---- - -- name: "1.5.1 | PATCH | Ensure core dump storage is disabled" - ansible.builtin.lineinfile: - path: /etc/systemd/coredump.conf - regexp: 'Storage=' - line: 'Storage=none' - notify: systemd_daemon_reload - when: - - rhel8cis_rule_1_5_1 - - systemd_coredump.stat.exists - tags: - - level1-server - - level1-workstation - - automated - - patch - - rule_1.5.1 - -- name: "1.5.2 | PATCH | Ensure core dump backtraces are disabled" - ansible.builtin.lineinfile: - path: /etc/systemd/coredump.conf - regexp: 'ProcessSizeMax=' - line: 'ProcessSizeMax=0' - when: - - rhel8cis_rule_1_5_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - sysctl - - rule_1.5.2 - -- name: "1.5.3 | PATCH | Ensure address space layout randomization (ASLR) is enabled" - ansible.posix.sysctl: - name: kernel.randomize_va_space - value: '2' - sysctl_set: true - ignoreerrors: true - when: - - rhel8cis_rule_1_5_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - sysctl - - rule_1.5.3 diff --git a/tasks/section_1/cis_1.6.1.x.yml b/tasks/section_1/cis_1.6.1.x.yml deleted file mode 100644 index fde021c7..00000000 --- a/tasks/section_1/cis_1.6.1.x.yml +++ /dev/null @@ -1,135 +0,0 @@ ---- - -- name: "1.6.1.1 | PATCH | Ensure SELinux is installed" - ansible.builtin.package: - name: libselinux - state: present - when: - - rhel8cis_rule_1_6_1_1 - tags: - - level1-server - - level1-workstation - - automated - - patch - - rule_1.6.1.1 - -- name: "1.6.1.2 | PATCH | Ensure SELinux is not disabled in bootloader configuration" - ansible.builtin.replace: - path: /etc/default/grub - regexp: '(selinux|enforcing)\s*=\s*0\s*' - replace: '' - register: selinux_grub_patch - ignore_errors: true # noqa ignore-errors - notify: rhel8cis_grub2cfg - when: - - rhel8cis_rule_1_6_1_2 - tags: - - level1-server - - level1-workstation - - patch - - rule_1.6.1.2 - -# State set to enforcing because control 1.6.1.5 requires enforcing to be set -- name: "1.6.1.3 | PATCH | Ensure SELinux policy is configured" - ansible.posix.selinux: - conf: /etc/selinux/config - policy: "{{ rhel8cis_selinux_policy }}" - state: "{{ rhel8cis_selinux_state }}" - when: - - not rhel8cis_selinux_disable - - rhel8cis_rule_1_6_1_3 - tags: - - level1-server - - level1-workstation - - automated - - selinux - - patch - - rule_1.6.1.3 - -# State set to enforcing because control 1.6.1.5 requires enforcing to be set -- name: "1.6.1.4 | PATCH | Ensure the SELinux mode is not disabled" - ansible.posix.selinux: - conf: /etc/selinux/config - policy: "{{ rhel8cis_selinux_policy }}" - state: "{{ rhel8cis_selinux_state }}" - when: - - not rhel8cis_selinux_disable - - rhel8cis_rule_1_6_1_4 - tags: - - level1-server - - level1-workstation - - automated - - selinux - - patch - - rule_1.6.1.4 - -- name: "1.6.1.5 | PATCH | Ensure the SELinux state is enforcing" - ansible.posix.selinux: - conf: /etc/selinux/config - policy: "{{ rhel8cis_selinux_policy }}" - state: enforcing - when: - - not rhel8cis_selinux_disable - - rhel8cis_rule_1_6_1_5 - tags: - - level2-server - - level2-workstation - - automated - - selinux - - patch - - rule_1.6.1.5 - -- name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist" - block: - - name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist | Find the unconfined services" - ansible.builtin.shell: ps -eZ | grep unconfined_service_t | egrep -vw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }' - register: rhelcis_1_6_1_6_unconf_services - failed_when: false - changed_when: false - - - name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist | Message on unconfined services" - ansible.builtin.debug: - msg: "Warning!! You have unconfined services: {{ rhelcis_1_6_1_6_unconf_services.stdout_lines }}" - when: rhelcis_1_6_1_6_unconf_services.stdout | length > 0 - - - name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist | warning count" - ansible.builtin.import_tasks: warning_facts.yml - when: rhelcis_1_6_1_6_unconf_services.stdout | length > 0 - vars: - warn_control_id: '1.6.1.6' - when: - - rhel8cis_rule_1_6_1_6 - tags: - - level1-server - - level1-workstation - - automated - - audit - - services - - rule_1.6.1.6 - -- name: "1.6.1.7 | PATCH | Ensure SETroubleshoot is not installed" - ansible.builtin.package: - name: setroubleshoot - state: absent - when: - - rhel8cis_rule_1_6_1_7 - - "'setroubleshoot' in ansible_facts.packages" - tags: - - level1-server - - automated - - selinux - - patch - - rule_1.6.1.7 - -- name: "1.6.1.8 | PATCH | Ensure the MCS Translation Service (mcstrans) is not installed" - ansible.builtin.package: - name: mcstrans - state: absent - when: - - rhel8cis_rule_1_6_1_8 - tags: - - level1-server - - level1-workstation - - automated - - patch - - rule_1.6.1.8 diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml new file mode 100644 index 00000000..604c03e9 --- /dev/null +++ b/tasks/section_1/cis_1.6.x.yml @@ -0,0 +1,91 @@ +--- + +- name: "1.6.1 | PATCH | Ensure system-wide crypto policy is not legacy" + when: + - rhel8cis_rule_1_6_1 + tags: + - level1-server + - level1-workstation + - automated + - no system_is_ec2 + - patch + - NIST800-53R5_SC-8 + - rule_1.6.1 + notify: Change_requires_reboot + block: + - name: "1.6.1 | PATCH | Ensure system-wide crypto policy is not legacy | set_fact" + ansible.builtin.set_fact: + rhel8cis_full_crypto_policy: "{{ rhel8cis_crypto_policy }}{% if rhel8cis_crypto_policy_module | length > 0 %}:{{ rhel8cis_crypto_policy_module }}{% endif %}" + + - name: "1.6.1 | PATCH | Ensure system-wide crypto policy is not legacy" + when: + - rhel8cis_system_wide_crypto_policy.stdout not in rhel8cis_crypto_policy + ansible.builtin.shell: | + update-crypto-policies --set "{{ rhel8cis_full_crypto_policy }}" + update-crypto-policies + +- name: "1.6.2 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support" + when: + - rhel8cis_rule_1_6_2 + - "'NO-SHA1' not in rhel8cis_system_wide_crypto_policy.stdout" + tags: + - level1-server + - level1-workstation + - automated + - no system_is_ec2 + - patch + - NIST800-53R5_SC-8 + - rule_1.6.2 + notify: Change_requires_reboot + block: + - name: "1.6.2 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | crypto_file" + ansible.builtin.template: + dest: /etc/crypto-policies/policies/modules/NO-SHA1.pmod + src: etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 + + - name: "1.6.2 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | set crypto policy" + ansible.builtin.shell: "update-crypto-policies --set {{ rhel8cis_full_crypto_policy }}:NO-SHA1" + +- name: "1.6.3 | PATCH | Ensure system wide crypto policy disables cbc for ssh" + when: + - rhel8cis_rule_1_6_3 + - "'NO-SSHCBC' not in rhel8cis_system_wide_crypto_policy.stdout" + tags: + - level1-server + - level1-workstation + - automated + - no system_is_ec2 + - patch + - NIST800-53R5_SC-8 + - rule_1.6.3 + notify: Change_requires_reboot + block: + - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables cbc for ssh | crypto_file" + ansible.builtin.template: + dest: /etc/crypto-policies/policies/modules/NO-SSHCBC.pmod + src: etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 + + - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables cbc for ssh | set crypto policy" + ansible.builtin.shell: "update-crypto-policies --set {{ rhel8cis_full_crypto_policy }}:{% if rhel8cis_rule_1_6_2 %}NO-SHA1:{% endif %}NO-SSHCBC" + +- name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits" + when: + - rhel8cis_rule_1_6_4 + - "'NO-WEAKMAC' not in rhel8cis_system_wide_crypto_policy.stdout" + tags: + - level1-server + - level1-workstation + - automated + - no system_is_ec2 + - patch + - NIST800-53R5_SC-8 + - rule_1.6.4 + notify: Change_requires_reboot + block: + - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables cbc for ssh | crypto_file" + ansible.builtin.template: + dest: /etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod + src: etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 + + - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables cbc for ssh | set crypto policy" + ansible.builtin.shell: "update-crypto-policies --set {{ rhel8cis_full_crypto_policy }}:{% if rhel8cis_rule_1_6_2 %}NO-SHA1:{% endif %}{% if rhel8cis_rule_1_6_3 %}NO-SSHCBC:{% endif %}NO-WEAKMAC" diff --git a/tasks/section_1/cis_1.7.x.yml b/tasks/section_1/cis_1.7.x.yml index c4745540..9c240b4e 100644 --- a/tasks/section_1/cis_1.7.x.yml +++ b/tasks/section_1/cis_1.7.x.yml @@ -1,12 +1,6 @@ --- - name: "1.7.1 | PATCH | Ensure message of the day is configured properly" - ansible.builtin.template: - src: etc/motd.j2 - dest: /etc/motd - owner: root - group: root - mode: 0644 when: - rhel8cis_rule_1_7_1 tags: @@ -15,15 +9,18 @@ - automated - banner - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-3 + - NIST800-53R5_CM-6 - rule_1.7.1 - -- name: "1.7.2 | PATCH | Ensure local login warning banner is configured properly" ansible.builtin.template: - src: etc/issue.j2 - dest: /etc/issue + src: etc/motd.j2 + dest: /etc/motd owner: root group: root - mode: 0644 + mode: go-rx + +- name: "1.7.2 | PATCH | Ensure local login warning banner is configured properly" when: - rhel8cis_rule_1_7_2 tags: @@ -31,15 +28,18 @@ - level1-workstation - automated - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-3 + - NIST800-53R5_CM-6 - rule_1.7.2 - -- name: "1.7.3 | PATCH | Ensure remote login warning banner is configured properly" ansible.builtin.template: - src: etc/issue.net.j2 - dest: /etc/issue.net + src: etc/issue.j2 + dest: /etc/issue owner: root group: root - mode: 0644 + mode: go-rx + +- name: "1.7.3 | PATCH | Ensure remote login warning banner is configured properly" when: - rhel8cis_rule_1_7_3 tags: @@ -48,15 +48,18 @@ - automated - banner - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-3 + - NIST800-53R5_CM-6 - rule_1.7.3 - -- name: "1.7.4 | PATCH | Ensure permissions on /etc/motd are configured" - ansible.builtin.file: - path: /etc/motd - state: file + ansible.builtin.template: + src: etc/issue.net.j2 + dest: /etc/issue.net owner: root group: root - mode: 0644 + mode: go-wx + +- name: "1.7.4 | PATCH | Ensure access to /etc/motd is configured" when: - rhel8cis_rule_1_7_4 tags: @@ -65,15 +68,17 @@ - automated - perms - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_1.7.4 - -- name: "1.7.5 | PATCH | Ensure permissions on /etc/issue are configured" ansible.builtin.file: - path: /etc/issue + path: /etc/motd state: file owner: root group: root - mode: 0644 + mode: go-wx + +- name: "1.7.5 | PATCH | Ensure access to /etc/issue is configured" when: - rhel8cis_rule_1_7_5 tags: @@ -82,15 +87,17 @@ - automated - perms - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_1.7.5 - -- name: "1.7.6 | PATCH | Ensure permissions on /etc/issue.net are configured" ansible.builtin.file: - path: /etc/issue.net + path: /etc/issue state: file owner: root group: root - mode: 0644 + mode: go-wx + +- name: "1.7.6 | PATCH | Ensure access to /etc/issue.net is configured" when: - rhel8cis_rule_1_7_6 tags: @@ -99,4 +106,12 @@ - automated - perms - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_1.7.6 + ansible.builtin.file: + path: /etc/issue.net + state: file + owner: root + group: root + mode: go-wx diff --git a/tasks/section_1/cis_1.8.x.yml b/tasks/section_1/cis_1.8.x.yml index 877a5756..b665c17e 100644 --- a/tasks/section_1/cis_1.8.x.yml +++ b/tasks/section_1/cis_1.8.x.yml @@ -1,9 +1,6 @@ --- - name: "1.8.1 | PATCH | Ensure GNOME Display Manager is removed" - ansible.builtin.package: - name: gdm - state: absent when: - rhel8cis_rule_1_8_1 - "'gdm' in ansible_facts.packages" @@ -15,8 +12,22 @@ - gui - gdm - rule_1.8.1 + ansible.builtin.package: + name: gdm + state: absent - name: "1.8.2 | PATCH | Ensure GDM login banner is configured" + when: + - rhel8cis_rule_1_8_2 + - rhel8cis_gui + tags: + - level1-server + - level1-workstation + - automated + - patch + - gui + - gdm + - rule_1.8.2 ansible.builtin.lineinfile: path: "{{ item.file }}" regexp: "{{ item.regexp }}" @@ -25,16 +36,35 @@ owner: root group: root mode: 0644 - notify: reload dconf - with_items: + notify: Reload_dconf + loop: - { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' } - { file: '/etc/dconf/profile/gdm', regexp: 'system-db', line: 'system-db:gdm' } - { file: '/etc/dconf/profile/gdm', regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults' } - { file: '/etc/dconf/db/gdm.d/01-banner-message', regexp: '\[org\/gnome\/login-screen\]', line: '[org/gnome/login-screen]' } - { file: '/etc/dconf/db/gdm.d/01-banner-message', regexp: 'banner-message-enable', line: 'banner-message-enable=true' } - { file: '/etc/dconf/db/gdm.d/01-banner-message', regexp: 'banner-message-text', line: "banner-message-text='{{ rhel8cis_warning_banner | replace('\n', ' ') }}' " } + +- name: "1.8.3 | PATCH | Ensure GDM disable-user-list option is enabled" + ansible.builtin.lineinfile: + path: "{{ item.file }}" + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + create: true + owner: root + group: root + mode: '0644' + notify: Reload_dconf + loop: + - { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' } + - { file: '/etc/dconf/profile/gdm', regexp: 'system-db', line: 'system-db:gdm' } + - { file: '/etc/dconf/profile/gdm', regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults'} + - { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: '\[org\/gnome\/login-screen\]', line: '[org/gnome/login-screen]' } + - { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: 'disable-user-list=', line: 'disable-user-list=true' } + +- name: "1.8.3 | PATCH | Ensure GDM disable-user-list option is enabled" when: - - rhel8cis_rule_1_8_2 + - rhel8cis_rule_1_8_3 - rhel8cis_gui tags: - level1-server @@ -42,10 +72,7 @@ - automated - patch - gui - - gdm - - rule_1.8.2 - -- name: "1.8.3 | PATCH | Ensure last logged in user display is disabled" + - rule_1.8.3 ansible.builtin.lineinfile: path: "{{ item.file }}" regexp: "{{ item.regexp }}" @@ -54,15 +81,17 @@ owner: root group: root mode: 0644 - notify: reload dconf - with_items: + notify: Reload_dconf + loop: - { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' } - { file: '/etc/dconf/profile/gdm', regexp: 'system-db', line: 'system-db:gdm' } - { file: '/etc/dconf/profile/gdm', regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults'} - { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: '\[org\/gnome\/login-screen\]', line: '[org/gnome/login-screen]' } - { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: 'disable-user-list=', line: 'disable-user-list=true' } + +- name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle" when: - - rhel8cis_rule_1_8_3 + - rhel8cis_rule_1_8_4 - rhel8cis_gui tags: - level1-server @@ -70,45 +99,179 @@ - automated - patch - gui - - rule_1.8.3 + - rule_1.8.4 + notify: Reload_dconf + block: + - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | User profile" + ansible.builtin.lineinfile: + path: /etc/dconf/profile/user + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + create: true + owner: root + group: root + mode: '0644' + loop: + - { regexp: '^user-db', line: 'user-db: user' } + - { regexp: '^system-db', line: 'system-db: local' } -- name: "1.8.4 | PATCH | Ensure XDMCP is not enabled" - ansible.builtin.lineinfile: - path: /etc/gdm/custom.conf - regexp: 'Enable=true' - state: absent + - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make db directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d" + owner: root + group: root + mode: '0755' + state: directory + + - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make conf file" + ansible.builtin.template: + src: etc/dconf/db/00-screensaver.j2 + dest: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/00-screensaver" + owner: root + group: root + mode: '0644' + +- name: "1.8.5 PATCH | Ensure GDM screen locks cannot be overridden" when: - - rhel8cis_rule_1_8_4 + - rhel8cis_rule_1_8_5 - rhel8cis_gui tags: - level1-server - - level1-workstation + - level2-workstation - automated - patch - gui - - rule_1.8.4 + - rule_1.8.5 + block: + - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/locks" + owner: root + group: root + mode: '0755' + state: directory -- name: "1.8.5 | PATCH | Ensure automatic mounting of removable media is disabled" - ansible.builtin.lineinfile: - path: /etc/dconf/db/local.d/00-media-automount - regexp: "{{ item.regex }}" - line: "{{ item.line }}" - create: true + - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock file" + ansible.builtin.template: + src: etc/dconf/db/locks/00-screensaver_lock.j2 + dest: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/locks/00-screensaver" + owner: root + group: root + mode: '0644' + +- name: "1.8.6 | PATCH | Ensure GDM automatic mounting of removable media is disabled" + when: + - rhel8cis_rule_1_8_6 + - rhel8cis_gui + tags: + - level1-server + - level2-workstation + - patch + - gui + - rule_1.8.6 + notify: Reload_dconf + ansible.builtin.template: + src: etc/dconf/db/00-media-automount.j2 + dest: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/00-media-automount" owner: root group: root - mode: 0640 - notify: reload dconf - with_items: - - { regex: '\[org\/gnome\/desktop\/media-handling\]', line: '[org/gnome/desktop/media-handling]' } - - { regex: 'automount=', line: 'automount=false' } - - { regex: 'automount-open=', line: 'automount-open=false'} + mode: '0644' + +- name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden" when: - - rhel8cis_rule_1_8_5 + - rhel8cis_rule_1_8_7 - rhel8cis_gui tags: - level1-server - level2-workstation - - automated - patch - gui - - rule_1.8.5 + - rule_1.8.7 + notify: Reload_dconf + block: + - name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden | Make lock directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/locks" + owner: root + group: root + mode: '0755' + state: directory + + - name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden | Make lock file" + ansible.builtin.template: + src: etc/dconf/db/locks/00-automount_lock.j2 + dest: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/locks/00-automount_lock" + owner: root + group: root + mode: '0644' + +- name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled" + when: + - rhel8cis_rule_1_8_8 + - rhel8cis_gui + tags: + - level1-server + - level2-workstation + - patch + - gui + - rule_1.8.8 + notify: Reload_dconf + block: + - name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d" + owner: root + group: root + mode: '0755' + state: directory + + - name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make conf file" + ansible.builtin.template: + src: etc/dconf/db/00-media-autorun.j2 + dest: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/00-media-autorun" + owner: root + group: root + mode: '0644' + +- name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden" + when: + - rhel8cis_rule_1_8_9 + - rhel8cis_gui + tags: + - level1-server + - level2-workstation + - patch + - gui + - rule_1.8.9 + notify: Reload_dconf + block: + - name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lock directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/locks" + owner: root + group: root + mode: '0755' + state: directory + + - name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lockfile" + ansible.builtin.template: + src: etc/dconf/db/locks/00-autorun_lock.j2 + dest: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/locks/00-autorun_lock" + owner: root + group: root + mode: '0644' + +- name: "1.8.10 | PATCH | Ensure XDMCP is not enabled" + when: + - rhel8cis_rule_1_8_10 + - rhel8cis_gui + tags: + - level1-server + - level1-workstation + - patch + - gui + - rule_1.8.10 + ansible.builtin.lineinfile: + path: /etc/gdm/custom.conf + regexp: 'Enable=true' + state: absent diff --git a/tasks/section_1/cis_1.9.yml b/tasks/section_1/cis_1.9.yml index f2bafe43..76113d6c 100644 --- a/tasks/section_1/cis_1.9.yml +++ b/tasks/section_1/cis_1.9.yml @@ -1,33 +1,18 @@ --- -- name: "1.9 | PATCH | Ensure updates, patches, and additional security software are installed" - ansible.builtin.package: - name: "*" - state: latest - notify: change_requires_reboot +- name: "1.1.9 | PATCH | Disable Automounting" + ansible.builtin.service: + name: autofs + enabled: false when: - - rhel8cis_rule_1_9 - - not system_is_ec2 + - not rhel8cis_allow_autofs + - "'autofs' in ansible_facts.packages" + - rhel8cis_rule_1_1_9 tags: - level1-server - - level1-workstation + - level2-workstation - automated - patch - - rule_1.9 - - skip_ansible_lint - -- name: "1.9 | PATCH | Ensure updates, patches, and additional security software are installed | limit kernels" - ansible.builtin.lineinfile: - path: /etc/dnf/dnf.conf - regexp: ^installonly_limit= - line: installonly_limit={{ rhel8cis_installed_kernel_limit }} - when: - - rhel8cis_rule_1_9 - - rhel8cis_apply_installed_kernel_limit - tags: - - level1-server - - level1-workstation - - automated - - patch - - kernel_limit - - rule_1.9 + - mounts + - automounting + - rule_1.1.9 diff --git a/tasks/section_1/main.yml b/tasks/section_1/main.yml index 8cdde142..ba9d119a 100644 --- a/tasks/section_1/main.yml +++ b/tasks/section_1/main.yml @@ -1,59 +1,63 @@ --- - name: "SECTION | 1.1.1.x | Disable unused filesystems" - ansible.builtin.import_tasks: cis_1.1.1.x.yml + ansible.builtin.import_tasks: + file: cis_1.1.1.x.yml -- name: "SECTION | 1.1.2.x | Configure /tmp" - ansible.builtin.import_tasks: cis_1.1.2.x.yml +- name: "SECTION | 1.1.2.1.x | Configure /tmp" + ansible.builtin.import_tasks: + file: cis_1.1.2.1.x.yml -- name: "SECTION | 1.1.3.x | Configure /var" - ansible.builtin.import_tasks: cis_1.1.3.x.yml +- name: "SECTION | 1.1.2.2.x | Configure /dev/shm" + ansible.builtin.import_tasks: + file: cis_1.1.2.2.x.yml -- name: "SECTION | 1.1.4.x | Configure /var/tmp" - ansible.builtin.import_tasks: cis_1.1.4.x.yml +- name: "SECTION | 1.1.2.3.x | Configure /home" + ansible.builtin.import_tasks: + file: cis_1.1.2.3.x.yml -- name: "SECTION | 1.1.5.x | Configure /var/log" - ansible.builtin.import_tasks: cis_1.1.5.x.yml +- name: "SECTION | 1.1.2.4.x | Configure /var" + ansible.builtin.import_tasks: + file: cis_1.1.2.4.x.yml -- name: "SECTION | 1.1.6.x | Configure /var/log/audit" - ansible.builtin.import_tasks: cis_1.1.6.x.yml +- name: "SECTION | 1.1.2.5.x | Configure /var/tmp" + ansible.builtin.import_tasks: + file: cis_1.1.2.5.x.yml -- name: "SECTION | 1.1.7.x | Configure /home" - ansible.builtin.import_tasks: cis_1.1.7.x.yml +- name: "SECTION | 1.1.2.6.x | Configure /var/log" + ansible.builtin.import_tasks: + file: cis_1.1.2.6.x.yml -- name: "SECTION | 1.1.8.x | Configure /dev/shm" - ansible.builtin.import_tasks: cis_1.1.8.x.yml +- name: "SECTION | 1.1.2.7.x | Configure /var/log/audit" + ansible.builtin.import_tasks: + file: cis_1.1.2.7.x.yml -- name: "SECTION | 1.1.x | Disable various mounting" - ansible.builtin.import_tasks: cis_1.1.x.yml +- name: "SECTION | 1.2 | DNF and updates" + ansible.builtin.import_tasks: + file: cis_1.2.x.yml -- name: "SECTION | 1.2 | Configure Software Updates" - ansible.builtin.import_tasks: cis_1.2.x.yml +- name: "SECTION | 1.3 | Bootloader" + ansible.builtin.import_tasks: + file: cis_1.3.x.yml -- name: "SECTION | 1.3 | Filesystem Integrity Checking" - ansible.builtin.import_tasks: cis_1.3.x.yml - when: rhel8cis_config_aide +- name: "SECTION | 1.4 | sysctl kernel" + ansible.builtin.import_tasks: + file: cis_1.4.x.yml -- name: "SECTION | 1.4 | Secure Boot Settings" - ansible.builtin.import_tasks: cis_1.4.x.yml - -- name: "SECTION | 1.5 | Additional Process Hardening" - ansible.builtin.import_tasks: cis_1.5.x.yml - -- name: "SECTION | 1.6 | Mandatory Access Control" - ansible.builtin.import_tasks: cis_1.6.1.x.yml +- name: "SECTION | 1.5 | SELinux" when: not rhel8cis_selinux_disable + ansible.builtin.import_tasks: + file: cis_1.5.1.x.yml + +- name: "SECTION | 1.6 | Crypto" + ansible.builtin.import_tasks: + file: cis_1.6.x.yml - name: "SECTION | 1.7 | Command Line Warning Banners" - ansible.builtin.import_tasks: cis_1.7.x.yml + ansible.builtin.import_tasks: + file: cis_1.7.x.yml - name: "SECTION | 1.8 | Gnome Display Manager" - ansible.builtin.import_tasks: cis_1.8.x.yml - -- name: "SECTION | 1.9 | Updates and Patches" - ansible.builtin.import_tasks: cis_1.9.yml - -- name: "SECTION | 1.10 | Crypto policies" - ansible.builtin.import_tasks: cis_1.10.yml - when: - - not system_is_ec2 + when: rhel8cis_gui + ansible.builtin.import_tasks: + file: cis_1.8.x.yml diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index 33143d23..0de15e28 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -1,9 +1,6 @@ --- - name: "2.1.1 | PATCH | Ensure time synchronization is in use" - ansible.builtin.package: - name: "{{ rhel8cis_time_synchronization }}" - state: present when: - rhel8cis_rule_2_1_1 - not system_is_container @@ -13,27 +10,11 @@ - automated - patch - rule_2.1.1 + ansible.builtin.package: + name: "{{ rhel8cis_time_synchronization }}" + state: present - name: "2.1.2 | PATCH | Ensure chrony is configured" - block: - - name: "2.1.2 | PATCH | Ensure chrony is configured | Set configuration" - ansible.builtin.template: - src: chrony.conf.j2 - dest: /etc/chrony.conf - owner: root - group: root - mode: 0644 - when: rhel8cis_chrony_ansible_managed - - - name: "2.1.2 | PATCH | Ensure chrony is configured | modify /etc/sysconfig/chronyd" - ansible.builtin.lineinfile: - path: /etc/sysconfig/chronyd - regexp: OPTIONS=\"(.*)(?!-u chrony)(.*)" - line: OPTIONS="\1\2 -u chrony" - create: true - backrefs: true - mode: '0644' - when: - rhel8cis_time_synchronization == "chrony" - rhel8cis_rule_2_1_2 @@ -42,4 +23,30 @@ - level1-server - level1-workstation - patch + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 - rule_2.1.2 + ansible.builtin.template: + src: chrony.conf.j2 + dest: /etc/chrony.conf + owner: root + group: root + mode: '0644' + +- name: "2.1.3 | PATCH | Ensure chrony is not run as the root user" + when: + - rhel8cis_time_synchronization == "chrony" + - rhel8cis_rule_2_1_3 + - not system_is_container + tags: + - level1-server + - level1-workstation + - patch + - rule_2.1.3 + ansible.builtin.lineinfile: + path: /etc/sysconfig/chronyd + regexp: OPTIONS=\"(.*)(?!-u chrony)(.*)" + line: OPTIONS="\1\2 -u chrony" + create: true + backrefs: true + mode: '0644' diff --git a/tasks/section_2/cis_2.2.x.yml b/tasks/section_2/cis_2.2.x.yml index 5b759b26..adfc8a91 100644 --- a/tasks/section_2/cis_2.2.x.yml +++ b/tasks/section_2/cis_2.2.x.yml @@ -1,106 +1,208 @@ --- -- name: "2.2.1 | PATCH | Ensure xinetd is not installed" - ansible.builtin.package: - name: xinetd - state: absent +- name: "2.2.1 | PATCH | Ensure autofs services are not in use" when: - rhel8cis_rule_2_2_1 - - not rhel8cis_xinetd_server - - "'xinetd' in ansible_facts.packages" + - "'autofs' in ansible_facts.packages" tags: - level1-server - - level1-workstation + - level2-workstation - automated - patch + - NIST800-53R5_SI-3 + - NIST800-53R5_MP-7 - rule_2.2.1 + block: + - name: "2.2.1 | PATCH | Ensure autofs services are not in use | Remove Package" + when: + - not rhel8cis_autofs_services + - not rhel8cis_autofs_mask + ansible.builtin.package: + name: autofs + state: absent -- name: "2.2.2 | PATCH | Ensure xorg-x11-server-common is not installed" - ansible.builtin.package: - name: xorg-x11-server-common - state: absent + - name: "2.2.1 | PATCH | Ensure autofs services are not in use | Mask service" + when: + - not rhel8cis_autofs_services + - rhel8cis_autofs_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: autofs + enabled: false + state: stopped + masked: true + +- name: "2.2.2 | PATCH | Ensure avahi daemon services are not in use" when: - rhel8cis_rule_2_2_2 - - "'xorg-x11-server-common' in ansible_facts.packages" - - not rhel8cis_xwindows_required or not rhel8cis_gui + - "'avahi' in ansible_facts.packages or 'avahi-autopd' in ansible_facts.packages" tags: - level1-server + - level2-workstation - automated - patch - - x11 + - avahi + - NIST800-53R5_SI-4 - rule_2.2.2 + block: + - name: "2.2.2 | PATCH | Ensure avahi daemon services are not in use | Remove package" + when: + - not rhel8cis_avahi_server + - not rhel8cis_avahi_mask + ansible.builtin.package: + name: + - avahi-autoipd + - avahi + state: absent -- name: "2.2.3 | PATCH | Ensure Avahi Server is not installed" - ansible.builtin.package: - name: - - avahi-autoipd - - avahi - state: absent + - name: "2.2.2 | PATCH | Ensure avahi daemon services are not in use | Mask service" + when: + - not rhel8cis_avahi_server + - rhel8cis_avahi_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - avahi-daemon.socket + - avahi-daemon.service + +- name: "2.2.3 | PATCH | Ensure dhcp server services are not in use" when: + - "'dhcp-server' in ansible_facts.packages" - rhel8cis_rule_2_2_3 - - not rhel8cis_avahi_server - - "'avahi' in ansible_facts.packages or 'avahi-autopd' in ansible_facts.packages" tags: - level1-server - - level2-workstation + - level1-workstation - automated - patch - - avahi + - dhcp + - NIST800-53R5_CM-7 - rule_2.2.3 + block: + - name: "2.2.3 | PATCH | Ensure dhcp server services are not in use | Remove package" + when: + - not rhel8cis_dhcp_server + - not rhel8cis_dhcp_mask + ansible.builtin.package: + name: dhcp-server + state: absent -- name: "2.2.4 | PATCH | Ensure CUPS is not installed" - ansible.builtin.package: - name: cups - state: absent + - name: "2.2.3 | PATCH | Ensure dhcp server services are not in use | Mask service" + when: + - not rhel8cis_dhcp_server + - rhel8cis_dhcp_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - dhcpd.service + - dhcpd6.service + +- name: "2.2.4 | PATCH | Ensure dns server services are not in use" when: - - not rhel8cis_cups_server - - "'cups' in ansible_facts.packages" - - rhel8cis_rule_2_2_3 + - "'bind' in ansible_facts.packages" + - rhel8cis_rule_2_2_4 tags: - level1-server + - level1-workstation - automated - patch - - cups + - dns + - NIST800-53R5_CM-7 - rule_2.2.4 + block: + - name: "2.2.4 | PATCH | Ensure dns server services are not in use | Remove package" + when: + - not rhel8cis_dns_server + - not rhel8cis_dns_mask + ansible.builtin.package: + name: bind + state: absent -- name: "2.2.5 | PATCH | Ensure DHCP Server is not installed" - ansible.builtin.package: - name: dhcp-server - state: absent + - name: "2.2.4 | PATCH | Ensure dns server services are not in use | Mask service" + when: + - not rhel8cis_dns_server + - rhel8cis_dns_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: named.service + enabled: false + state: stopped + masked: true + +- name: "2.2.5 | PATCH | Ensure dnsmasq server services are not in use" when: - - not rhel8cis_dhcp_server - - "'dhcp-server' in ansible_facts.packages" + - "'dnsmasq' in ansible_facts.packages" - rhel8cis_rule_2_2_5 tags: - level1-server - level1-workstation - - audtomated + - automated - patch - - dhcp + - dns + - NIST800-53R5_CM-7 - rule_2.2.5 + block: + - name: "2.2.5 | PATCH | Ensure dnsmasq server services are not in use | Remove package" + when: + - not rhel8cis_dnsmasq_server + - not rhel8cis_dnsmasq_mask + ansible.builtin.package: + name: dnsmasq + state: absent -- name: "2.2.6 | PATCH | Ensure DNS Server is not installed" - ansible.builtin.package: - name: bind - state: absent + - name: "2.2.5 | PATCH | Ensure dnsmasq server services are not in use | Mask service" + when: + - not rhel8cis_dnsmasq_server + - rhel8cis_dnsmasq_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: dnsmasq.service + enabled: false + state: stopped + masked: true + +- name: "2.2.6 | PATCH | Ensure samba file server services are not in use" when: - - not rhel8cis_dns_server - - "'bind' in ansible_facts.packages" + - "'samba' in ansible_facts.packages" - rhel8cis_rule_2_2_6 tags: - level1-server - level1-workstation - automated - patch - - dns + - samba + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 - rule_2.2.6 + block: + - name: "2.2.6 | PATCH | Ensure samba file server services are not in use | Remove package" + when: + - not rhel8cis_samba_server + - not rhel8cis_samba_mask + ansible.builtin.package: + name: samba + state: absent -- name: "2.2.7 | PATCH | Ensure FTP Server is not installed" - ansible.builtin.package: - name: ftp - state: absent + - name: "2.2.6 | PATCH | Ensure samba file server services are not in use | Mask service" + when: + - not rhel8cis_samba_server + - rhel8cis_samba_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: smb.service + enabled: false + state: stopped + masked: true + +- name: "2.2.7 | PATCH | Ensure ftp server services are not in use" when: - - not rhel8cis_ftp_server - "'ftp' in ansible_facts.packages" - rhel8cis_rule_2_2_7 tags: @@ -109,127 +211,243 @@ - automation - patch - ftp + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 - rule_2.2.7 + block: + - name: "2.2.7 | PATCH | Ensure ftp server services are not in use | Remove package" + when: + - not rhel8cis_ftp_server + - not rhel8cis_ftp_mask + ansible.builtin.package: + name: vsftpd + state: absent -- name: "2.2.8 | PATCH | Ensure VSFTP Server is not installed" - ansible.builtin.package: - name: vsftpd - state: absent + - name: "2.2.7 | PATCH | Ensure ftp server services are not in use | Mask service" + when: + - not rhel8cis_ftp_server + - rhel8cis_ftp_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: vsftpd.service + enabled: false + state: stopped + masked: true + +- name: "2.2.8 | PATCH | Ensure message access server services are not in use" when: - - not rhel8cis_vsftpd_server - - "'vsftpd' in ansible_facts.packages" + - "'dovecot' in ansible_facts.packages or 'cyrus-imapd' in ansible_facts.packages" - rhel8cis_rule_2_2_8 tags: - level1-server - level1-workstation - automated - patch - - vsftpd + - dovecot + - imap + - pop3 + - NIST800-53R5_CM-7 - rule_2.2.8 + block: + - name: "2.2.8 | PATCH | Ensure message access server services are not in use | Remove package" + when: + - not rhel8cis_message_server + - not rhel8cis_message_mask + ansible.builtin.package: + name: + - dovecot + - cyrus-imapd + state: absent -- name: "2.2.9 | PATCH | Ensure TFTP Server is not installed" - ansible.builtin.package: - name: tftp-server - state: absent + - name: "2.2.8 | PATCH | Ensure message access server services are not in use | Mask service" + when: + - not rhel8cis_message_server + - rhel8cis_message_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - "dovecot.socket" + - "dovecot.service" + - "cyrus-imapd.service" + +- name: "2.2.9 | PATCH | Ensure network file system services are not in use" when: - - not rhel8cis_tftp_server - - "'tftp-server' in ansible_facts.packages" + - "'nfs-utils' in ansible_facts.packages" - rhel8cis_rule_2_2_9 tags: - level1-server - level1-workstation - automated - patch - - tftp + - nfs + - services + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 - rule_2.2.9 - -- name: "2.2.10 | PATCH | Ensure a web server is not installed" block: - - name: "2.2.10 | PATCH | Ensure a web server is not installed | Remove httpd server" - ansible.builtin.package: - name: httpd - state: absent + - name: "2.2.9 | PATCH | Ensure network file system services are not in use | Remove package" when: - - not rhel8cis_httpd_server - - "'httpd' in ansible_facts.packages" - - - name: "2.2.10 | PATCH | Ensure a web server is not installed | Remove nginx server" + - not rhel8cis_nfs_server + - not rhel8cis_nfs_mask ansible.builtin.package: - name: nginx + name: nfs-utils state: absent + + - name: "2.2.9 | PATCH | Ensure network file system services are not in use | Mask service" when: - - not rhel8cis_nginx_server - - "'nginx' in ansible_facts.packages" + - not rhel8cis_nfs_server + - rhel8cis_nfs_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: nfs-server.service + enabled: false + state: stopped + masked: true + +- name: "2.2.10 | PATCH | Ensure nis server services are not in use" when: + - "'ypserv' in ansible_facts.packages" - rhel8cis_rule_2_2_10 tags: - level1-server - level1-workstation - automated - patch - - httpd - - nginx - - webserver + - nis + - NIST800-53R5_CM-7 - rule_2.2.10 + notify: Systemd_daemon_reload + block: + - name: "2.2.10 | PATCH | Ensure nis server services are not in use | Remove package" + when: + - not rhel8cis_nis_server + - not rhel8cis_nis_mask + ansible.builtin.package: + name: ypserv + state: absent -- name: "2.2.11 | PATCH | Ensure IMAP and POP3 server is not installed" - ansible.builtin.package: - name: - - dovecot - - cyrus-imapd - state: absent + - name: "2.2.10 | PATCH | Ensure nis server services are not in use | Mask service" + when: + - not rhel8cis_nis_server + - rhel8cis_nis_mask + ansible.builtin.systemd: + name: ypserv.service + enabled: false + state: stopped + masked: true + +- name: "2.2.11 | PATCH | Ensure print server services are not in use" when: - - not rhel8cis_dovecot_cyrus_server - - "'dovecot' in ansible_facts.packages or 'cyrus-imapd' in ansible_facts.packages" + - "'cups' in ansible_facts.packages" - rhel8cis_rule_2_2_11 tags: - level1-server - - level1-workstation - automated - patch - - dovecot - - imap - - pop3 + - cups + - NIST800-53R5_CM-7 - rule_2.2.11 + block: + - name: "2.2.11 | PATCH | Ensure print server services are not in use | Remove package" + when: + - not rhel8cis_print_server + - not rhel8cis_print_mask + ansible.builtin.package: + name: cups + state: absent -- name: "2.2.12 | PATCH | Ensure Samba is not enabled" - ansible.builtin.package: - name: samba - state: absent + - name: "2.2.11 | PATCH | Ensure print server services are not in use | Mask service" + when: + - not rhel8cis_print_server + - rhel8cis_print_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - "cups.socket" + - "cups.service" + +- name: "2.2.12 | PATCH | Ensure rpcbind services are not in use" when: - - not rhel8cis_samba_server - - "'samba' in ansible_facts.packages" + - "'rpcbind' in ansible_facts.packages" - rhel8cis_rule_2_2_12 tags: - level1-server - level1-workstation - automated - patch - - samba + - rpc + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 - rule_2.2.12 + block: + - name: "2.2.12 | PATCH | Ensure rpcbind services are not in use | Remove package" + when: + - not rhel8cis_rpc_server + - not rhel8cis_rpc_mask + ansible.builtin.package: + name: cups + state: absent -- name: "2.2.13 | PATCH | Ensure HTTP Proxy Server is not installed" - ansible.builtin.package: - name: squid - state: absent + - name: "2.2.12 | PATCH | Ensure rpcbind services are not in use | Mask service" + when: + - not rhel8cis_rpc_server + - rhel8cis_rpc_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - rpcbind.service + - rpcbind.socket + +- name: "2.2.13 | PATCH | Ensure rsync services are not in use" when: - - not rhel8cis_squid_server - - "'squid' in ansible_facts.packages" - - rhel8cis_rule_2_2_6 + - "'rsync-daemon' in ansible_facts.packages" + - rhel8cis_rule_2_2_13 tags: - level1-server - level1-workstation - - automation + - automated - patch - - squid + - rsync + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 - rule_2.2.13 + block: + - name: "2.2.13 | PATCH | Ensure rsync services are not in use | Remove package" + when: + - not rhel8cis_rsync_server + - not rhel8cis_rsync_mask + ansible.builtin.package: + name: rsync-daemon + state: absent -- name: "2.2.14 | PATCH | Ensure net-snmp is not installed" - ansible.builtin.package: - name: net-snmp - state: absent + - name: "2.2.13 | PATCH | Ensure rsync services are not in use | Mask service" + when: + - not rhel8cis_rsync_server + - rhel8cis_rsync_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - 'rsyncd.socket' + - 'rsyncd.service' + +- name: "2.2.14 | PATCH | Ensure snmp services are not in use" when: - - not rhel8cis_net_snmp_server - "'net-snmp' in ansible_facts.packages" - rhel8cis_rule_2_2_14 tags: @@ -238,162 +456,281 @@ - automation - patch - snmp + - NIST800-53R5_CM-7 - rule_2.2.14 + block: + - name: "2.2.14 | PATCH | Ensure snmp services are not in use | Remove package" + when: + - not rhel8cis_net_snmp_server + - not rhel8cis_net_snmp_mask + ansible.builtin.package: + name: rsync-daemon + state: absent -- name: "2.2.15 | PATCH | Ensure NIS Server is not installed" - ansible.builtin.package: - name: ypserv - state: absent + - name: "2.2.14 | PATCH | Ensure snmp services are not in use | Mask service" + when: + - not rhel8cis_net_snmp_server + - rhel8cis_net_snmp_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: snmpd.service + enabled: false + state: stopped + masked: true + +- name: "2.2.15 | PATCH | Ensure telnet server services are not in use" when: - - not rhel8cis_nis_server - - "'ypserv' in ansible_facts.packages" + - "'telnet-server' in ansible_facts.packages" - rhel8cis_rule_2_2_15 tags: - level1-server - level1-workstation - automated - patch - - nis + - telnet + - NIST800-53R5_CM-7 + - NIST800-53R5_CM-11 - rule_2.2.15 + block: + - name: "2.2.15 | PATCH | Ensure telnet server services are not in use | Remove package" + when: + - not rhel8cis_telnet_server + - not rhel8cis_telnet_mask + ansible.builtin.package: + name: telnet-server + state: absent -- name: "2.2.16 | PATCH | Ensure telnet-server is not installed" - ansible.builtin.package: - name: telnet-server - state: absent + - name: "2.2.15 | PATCH | Ensure telnet server services are not in use | Mask service" + when: + - not rhel8cis_telnet_server + - rhel8cis_telnet_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: telnet.socket + enabled: false + state: stopped + masked: true + +- name: "2.2.16 | PATCH | Ensure tftp server services are not in use" when: - - not rhel8cis_telnet_server - - "'telnet-server' in ansible_facts.packages" + - "'tftp-server' in ansible_facts.packages" - rhel8cis_rule_2_2_16 tags: - level1-server - level1-workstation - automated - patch - - telnet + - tftp + - NIST800-53R5_CM-7 - rule_2.2.16 + block: + - name: "2.2.16 | PATCH | Ensure tftp server services are not in use | Remove package" + when: + - not rhel8cis_tftp_server + - not rhel8cis_tftp_mask + ansible.builtin.package: + name: tftp-server + state: absent -- name: "2.2.17 | PATCH | Ensure mail transfer agent is configured for local-only mode" - ansible.builtin.lineinfile: - path: /etc/postfix/main.cf - regexp: "^(#)?inet_interfaces" - line: "inet_interfaces = loopback-only" - notify: restart postfix + - name: "2.2.16 | PATCH | Ensure tftp server services are not in use | Mask service" + when: + - not rhel8cis_tftp_server + - rhel8cis_tftp_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - 'tftp.socket' + - 'tftp.service' + +- name: "2.2.17 | PATCH | Ensure web proxy server services are not in use" when: - - not rhel8cis_is_mail_server - - "'postfix' in ansible_facts.packages" - - rhel8cis_rule_2_2_17 + - "'squid' in ansible_facts.packages" + - rhel8cis_rule_2_217 tags: - level1-server - level1-workstation - - automated + - automation - patch - - postfix + - squid + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 - rule_2.2.17 - -# The name title of the service says mask the service or remove packages -# Option available -- name: "2.2.18 | PATCH | Ensure nfs-utils is not installed or the nfs-server service is masked" block: - - name: "2.2.18 | PATCH | Ensure nfs-utils is not installed or the nfs-server service is masked | Remove package" + - name: "2.2.17 | PATCH | Ensure web proxy server services are not in use | Remove package" + when: + - not rhel8cis_squid_server + - not rhel8cis_squid_mask ansible.builtin.package: - name: nfs-utils + name: tftp-server state: absent - when: - - not rhel8cis_nfs_server - - not rhel8cis_nfs_mask - - name: "2.2.18 | PATCH | Ensure nfs-utils is not installed or the nfs-server service is masked | Mask service" + - name: "2.2.17 | PATCH | Ensure web proxy server services are not in use | Mask service" + when: + - not rhel8cis_squid_server + - rhel8cis_squid_mask notify: Systemd_daemon_reload ansible.builtin.systemd: - name: nfs-server.service + name: squid.service enabled: false state: stopped masked: true - when: - - not rhel8cis_nfs_server - - rhel8cis_nfs_mask + +- name: "2.2.18 | PATCH | Ensure web server services are not in use" when: - - "'nfs-utils' in ansible_facts.packages" - rhel8cis_rule_2_2_18 tags: - level1-server - level1-workstation - automated - patch - - nfs - - services + - httpd + - nginx + - webserver + - NIST800-53R5_CM-7 - rule_2.2.18 - -# The name title of the service says mask the service or remove packages -# Option available -- name: "2.2.19 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked" block: - - name: "2.2.19 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked | Remove package" + - name: "2.2.18 | PATCH | Ensure web server services are not in use | Remove httpd server" + when: + - not rhel8cis_httpd_server + - not rhel8cis_httpd_mask + - "'httpd' in ansible_facts.packages" ansible.builtin.package: - name: cups + name: httpd state: absent + + - name: "2.2.18 | PATCH | Ensure web server services are not in use | Remove nginx server" when: - - not rhel8cis_rpc_server - - not rhel8cis_rpc_mask + - not rhel8cis_nginx_server + - not rhel8cis_nginx_mask + - "'nginx' in ansible_facts.packages" + ansible.builtin.package: + name: nginx + state: absent - - name: "2.2.19 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked | Mask service" + - name: "2.2.18 | PATCH | Ensure web server services are not in use | Mask httpd service" + when: + - not rhel8cis_httpd_server + - rhel8cis_httpd_mask + - "'httpd' in ansible_facts.packages" notify: Systemd_daemon_reload ansible.builtin.systemd: - name: "{{ item }}" + name: httpd.service enabled: false state: stopped masked: true - loop: - - rpcbind.service - - rpcbind.socket + + - name: "2.2.18 | PATCH | Ensure web server services are not in use | Mask nginx service" when: - - not rhel8cis_rpc_server - - rhel8cis_rpc_mask + - not rhel8cis_nginx_server + - rhel8cis_nginx_mask + - "'nginx' in ansible_facts.packages" + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: ngnix.service + enabled: false + state: stopped + masked: true + +- name: "2.2.19 | PATCH | Ensure xinetd services are not in use" when: - - not rhel8cis_rpc_server - - "'rpcbind' in ansible_facts.packages" + - "'xinetd' in ansible_facts.packages" - rhel8cis_rule_2_2_19 tags: - level1-server - level1-workstation - automated - patch - - rpc + - xinetd + - NIST800-53R5_CM-7 - rule_2.2.19 - -# The name title of the service says mask the service or remove packages -# Option available -- name: "2.2.20 | PATCH | Ensure rsync is not installed or the rsyncd service is masked" block: - - name: "2.2.20 | PATCH | Ensure rsync is not installed or the rsyncd service is masked | Remove package" + - name: "2.2.19 | PATCH | Ensure xinetd services are not in use | Remove package" + when: + - not rhel8cis_xinetd_server + - not rhel8cis_xinetd_mask ansible.builtin.package: - name: rsync-daemon + name: tftp-server state: absent - when: - - not rhel8cis_rsync_server - - not rhel8cis_rsync_mask - - name: "2.2.20 | PATCH | Ensure rsync is not installed or the rsyncd service is masked | Mask service" + - name: "2.2.19 | PATCH | Ensure xinetd services are not in use | Mask service" + when: + - not rhel8cis_xinetd_server + - rhel8cis_xinetd_mask notify: Systemd_daemon_reload ansible.builtin.systemd: - name: "{{ item }}" + name: xinetd.service enabled: false state: stopped masked: true - loop: - - 'rsyncd.socket' - - 'rsyncd.service' - when: - - not rhel8cis_rsync_server - - rhel8cis_rsync_mask + +- name: "2.2.20 | PATCH | Ensure X window server services are not in use" when: - - not rhel8cis_rsync_server - - "'rsync-daemon' in ansible_facts.packages" + - not rhel8cis_xwindow_server + - "'xorg-x11-server-common' in ansible_facts.packages" - rhel8cis_rule_2_2_20 tags: - level1-server - level1-workstation - automated - patch - - rsync + - xwindow + - NIST800-53R5_CM-11 - rule_2.2.20 + ansible.builtin.package: + name: xorg-x11-server-common + state: absent + +- name: "2.2.21 | PATCH | Ensure mail transfer agents are configured for local-only mode" + when: + - not rhel8cis_is_mail_server + - "'postfix' in ansible_facts.packages" + - rhel8cis_rule_2_2_21 + tags: + - level1-server + - level1-workstation + - automated + - patch + - postfix + - NIST800-53R5_CM-7 + - rule_2.2.21 + notify: Restart_postfix + ansible.builtin.lineinfile: + path: /etc/postfix/main.cf + regexp: "^(#)?inet_interfaces" + line: "inet_interfaces = loopback-only" + +- name: "2.2.22 | AUDIT | Ensure only approved services are listening on a network interface" + when: + - rhel8cis_rule_2_2_22 + tags: + - level1-server + - level1-workstation + - manual + - audit + - services + - NIST800-53R5_CM-7 + - rule_2.2.22 + vars: + warn_control_id: '2.2.22' + block: + - name: "2.2.22 | AUDIT | Ensure only approved services are listening on a network interface | Get list of services" + ansible.builtin.shell: systemctl list-units --type=service + changed_when: false + failed_when: rhel8cis_2_2_22_services.rc not in [ 0, 1 ] + check_mode: false + register: rhel8cis_2_2_22_services + + - name: "2.2.22 | AUDIT | Ensure only approved services are listening on a network interface | Display list of services" + ansible.builtin.debug: + msg: + - "Warning!! Below are the list of services, both active and inactive" + - "Please review to make sure all are essential" + - "{{ rhel8cis_2_2_22_services.stdout_lines }}" + + - name: "2.2.22 | AUDIT | Ensure only approved services are listening on a network interface | Warn Count" + ansible.builtin.import_tasks: + file: warning_facts.yml diff --git a/tasks/section_2/cis_2.3.x.yml b/tasks/section_2/cis_2.3.x.yml index 1c033a1b..9d3c16a4 100644 --- a/tasks/section_2/cis_2.3.x.yml +++ b/tasks/section_2/cis_2.3.x.yml @@ -1,57 +1,57 @@ --- -- name: "2.3.1 | PATCH | Ensure NIS Client is not installed" - ansible.builtin.package: - name: ypbind - state: absent +- name: "2.3.1 | PATCH | Ensure ftp client is not installed" when: - - not rhel8cis_ypbind_required - - "'ypbind' in ansible_facts.packages" + - not rhel8cis_ftp_client + - "'ftp' in ansible_facts.packages" - rhel8cis_rule_2_3_1 tags: - level1-server - level1-workstation - automated - patch - - nis + - ftp + - NIST800-53R5_CM-7 - rule_2.3.1 - -- name: "2.3.2 | PATCH | Ensure rsh client is not installed" ansible.builtin.package: - name: rsh + name: ftp state: absent + +- name: "2.3.2 | PATCH | Ensure ldap client is not installed" when: - - not rhel8cis_rsh_required - - "'rsh' in ansible_facts.packages" + - not rhel8cis_openldap_clients_required + - "'openldap-clients' in ansible_facts.packages" - rhel8cis_rule_2_3_2 tags: - - level1-server - level2-server + - level2-workstation - automated - patch - - rsh + - ldap + - NIST800-53R5_CM-7 - rule_2.3.2 - -- name: "2.3.3 | PATCH | Ensure talk client is not installed" ansible.builtin.package: - name: talk + name: openldap-clients state: absent + +- name: "2.3.3 | PATCH | Ensure nis client is not installed" when: - - not rhel8cis_talk_required - - "'talk' in ansible_facts.packages" + - not rhel8cis_ypbind_required + - "'ypbind' in ansible_facts.packages" - rhel8cis_rule_2_3_3 tags: - level1-server - level1-workstation - automated - patch - - talk + - nis + - NIST800-53R5_CM-7 - rule_2.3.3 - -- name: "2.3.4 | PATCH | Ensure telnet client is not installed" ansible.builtin.package: - name: telnet + name: ypbind state: absent + +- name: "2.3.4 | PATCH | Ensure telnet client is not installed" when: - not rhel8cis_telnet_required - "'telnet' in ansible_facts.packages" @@ -62,36 +62,25 @@ - automated - patch - telnet + - NIST800-53R5_CM-7 - rule_2.3.4 - -- name: "2.3.5 | PATCH | Ensure LDAP client is not installed" ansible.builtin.package: - name: openldap-clients + name: telnet state: absent + +- name: "2.3.5 | PATCH | Ensure TFTP client is not installed" when: - - not rhel8cis_openldap_clients_required - - "'openldap-clients' in ansible_facts.packages" + - not rhel8cis_tftp_client + - "'tftp' in ansible_facts.packages" - rhel8cis_rule_2_3_5 tags: - level1-server - level1-workstation - automated - patch - - ldap + - tftp + - NIST800-53R5_CM-7 - rule_2.3.5 - -- name: "2.3.6 | PATCH | Ensure TFTP client is not installed" ansible.builtin.package: name: tftp state: absent - when: - - not rhel8cis_tftp_client - - "'tftp' in ansible_facts.packages" - - rhel8cis_rule_2_3_6 - tags: - - level1-server - - level1-workstation - - automated - - patch - - tftp - - rule_2.3.6 diff --git a/tasks/section_2/cis_2.4.yml b/tasks/section_2/cis_2.4.yml deleted file mode 100644 index 1b60c8ad..00000000 --- a/tasks/section_2/cis_2.4.yml +++ /dev/null @@ -1,31 +0,0 @@ ---- - -- name: "2.4 | AUDIT | Ensure nonessential services are removed or masked" - block: - - name: "2.4 | AUDIT | Ensure nonessential services are removed or masked | Get list of services" - ansible.builtin.shell: systemctl list-units --type=service - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_2_4_services - - - name: "2.4 | AUDIT | Ensure nonessential services are removed or masked | Display list of services" - ansible.builtin.debug: - msg: - - "Warning!! Below are the list of services, both active and inactive" - - "Please review to make sure all are essential" - - "{{ rhel8cis_2_4_services.stdout_lines }}" - - - name: "2.4 | AUDIT | Ensure nonessential services are removed or masked | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '2.4' - when: - - rhel8cis_rule_2_4 - tags: - - level1-server - - level1-workstation - - manual - - audit - - services - - rule_2.4 diff --git a/tasks/section_2/main.yml b/tasks/section_2/main.yml index 39b912d5..8b9a094d 100644 --- a/tasks/section_2/main.yml +++ b/tasks/section_2/main.yml @@ -1,13 +1,13 @@ --- - name: "SECTION | 2.1 | Time Synchronization" - ansible.builtin.import_tasks: cis_2.1.x.yml + ansible.builtin.import_tasks: + file: cis_2.1.x.yml - name: "SECTION | 2.2 | Special Purpose Services" - ansible.builtin.import_tasks: cis_2.2.x.yml + ansible.builtin.import_tasks: + file: cis_2.2.x.yml - name: "SECTION | 2.3 | Service Clients" - ansible.builtin.import_tasks: cis_2.3.x.yml - -- name: "SECTION | 2.4 | Nonessential services removed" - ansible.builtin.import_tasks: cis_2.4.yml + ansible.builtin.import_tasks: + file: cis_2.3.x.yml diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index f704a17d..c2f83bd4 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -4,6 +4,19 @@ # We are using the rhel8cis_ipv6_required to specify if you have IPv6 in use - name: "3.1.1 | PATCH | Verify if IPv6 is enabled on the system" + when: + - not rhel8cis_ipv6_required + - rhel8cis_rule_3_1_1 + tags: + - level1-server + - level1-workstation + - manual + - patch + - ipv6 + - networking + - NIST800-53R5_CM-7 + - rule_3.1.1 + notify: Change_requires_reboot block: - name: "3.1.1 | PATCH | Verify if IPv6 is enabled on the system | disable all except localhost" ansible.posix.sysctl: @@ -11,122 +24,86 @@ value: '1' sysctl_set: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - with_items: + loop: - net.ipv6.conf.all.disable_ipv6 - net.ipv6.conf.default.disable_ipv6 - name: "3.1.1 | PATCH | Verify if IPv6 is enabled on the system | disable localhost sysctl" + when: + - rhel8cis_ipv6_disable_localhost ansible.posix.sysctl: name: net.ipv6.conf.lo.disable_ipv6 value: '1' sysctl_set: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: change_requires_reboot - when: - - rhel8cis_ipv6_disable_localhost - name: "3.1.1 | PATCH | Verify if IPv6 is enabled on the system | disable localhost /etc/hosts" + when: + - rhel8cis_ipv6_disable_localhost ansible.builtin.lineinfile: path: /etc/hosts regexp: '^(::1.*)' line: '#\1' backrefs: true - notify: change_requires_reboot - when: - - rhel8cis_ipv6_disable_localhost - - when: - - not rhel8cis_ipv6_required - - rhel8cis_rule_3_1_1 - tags: - - level1-server - - level1-workstation - - manual - - patch - - ipv6 - - networking - - rule_3.1.1 - -- name: "3.1.2 | PATCH | Ensure SCTP is disabled" - block: - - name: "3.1.2 | PATCH | Ensure SCTP is disabled | CIS" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/CIS.conf - regexp: "^(#)?install sctp(\\s|$)" - line: "install sctp /bin/true" - create: true - mode: 0600 - - name: "3.1.2 | PATCH | Ensure SCTP is disabled | blacklist" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/blacklist.conf - regexp: "^(#)?blacklist sctp(\\s|$)" - line: "blacklist sctp" - create: true - mode: 0600 +- name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled" when: - rhel8cis_rule_3_1_2 tags: - - level2-server - - level2-workstation + - level1-server - automated - patch - - sctp + - wireless + - NIST800-53R5_CM-7 - rule_3.1.2 - -- name: "3.1.3 | PATCH | Ensure DCCP is disabled" block: - - name: "3.1.3 | PATCH | Ensure DCCP is disabled | CIS" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/CIS.conf - regexp: "^(#)?install dccp(\\s|$)" - line: "install dccp /bin/true" - create: true - mode: 0600 - - - name: "3.1.3 | PATCH | Ensure DCCP is disabled | blacklist" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/blacklist.conf - regexp: "^(#)?blacklist dccp(\\s|$)" - line: "blacklist dccp" - create: true - mode: 0600 - when: - - rhel8cis_rule_3_1_3 - tags: - - level2-server - - level2-workstation - - automated - - dccp - - patch - - rule_3.1.3 - -- name: "3.1.4 | PATCH | Ensure wireless interfaces are disabled" - block: - - name: "3.1.4 | AUDIT | Ensure wireless interfaces are disabled | Check if nmcli command is available" + - name: "3.1.2 | AUDIT | Ensure wireless interfaces are disabled | Check if nmcli command is available" ansible.builtin.shell: rpm -q NetworkManager changed_when: false failed_when: false check_mode: false register: rhel_08_nmcli_available - - name: "3.1.4 | AUDIT | Ensure wireless interfaces are disabled | Check if wifi is enabled" + - name: "3.1.2 | AUDIT | Ensure wireless interfaces are disabled | Check if wifi is enabled" + when: rhel_08_nmcli_available.rc == 0 ansible.builtin.shell: nmcli radio wifi register: rhel_08_wifi_enabled changed_when: rhel_08_wifi_enabled.stdout != "disabled" failed_when: false - when: rhel_08_nmcli_available.rc == 0 - - name: "3.1.4 | PATCH | Ensure wireless interfaces are disabled | Disable wifi if enabled" + - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Disable wifi if enabled" + when: rhel_08_wifi_enabled is changed # noqa: no-handler ansible.builtin.shell: nmcli radio all off changed_when: false failed_when: false - when: rhel_08_wifi_enabled is changed # noqa: no-handler + +- name: "3.1.3 | PATCH | Ensure bluetooth services are not in use" when: - - rhel8cis_rule_3_1_4 + - rhel8cis_rule_3_1_3 tags: - level1-server + - level2-workstation - automated - patch - - wireless - - rule_3.1.4 + - sctp + - NIST800-53R5_CM-7 + - rule_3.1.3 + block: + - name: "3.1.3 | PATCH | Ensure bluetooth services are not in use | pkg" + when: + - not rhel8cis_bluetooth_service + - not rhel8cis_bluetooth_mask + ansible.builtin.package: + name: bluez + state: absent + + - name: "3.1.3 | PATCH | Ensure bluetooth services are not in use | mask" + when: + - not rhel8cis_bluetooth_service + - rhel8cis_bluetooth_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: bluetooth.service + enabled: false + state: stopped + masked: true diff --git a/tasks/section_3/cis_3.2.x.yml b/tasks/section_3/cis_3.2.x.yml index 0e8707e5..97fa0aa4 100644 --- a/tasks/section_3/cis_3.2.x.yml +++ b/tasks/section_3/cis_3.2.x.yml @@ -1,54 +1,118 @@ --- -- name: "3.2.1 | PATCH | Ensure IP forwarding is disabled" - block: - - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv4 forwarding" - ansible.posix.sysctl: - name: net.ipv4.ip_forward - value: '0' - ignoreerrors: true - sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table - - - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding" - ansible.posix.sysctl: - name: net.ipv6.conf.all.forwarding - value: '0' - ignoreerrors: true - sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv6 route table - when: - - rhel8cis_ipv6_required or - rhel8cis_ipv6_sysctl_force +- name: "3.2.1 | PATCH | Ensure dccp kernel module is not available" when: - - not rhel8cis_is_router - rhel8cis_rule_3_2_1 tags: - - level1-server - - level1-workstation + - level2-server + - level2-workstation - automated - - sysctl + - dccp - patch + - NIST800-53R5_CM-7 + - NIST800-53R5_SI-4 - rule_3.2.1 + block: + - name: "3.2.1 | PATCH | Ensure dccp kernel module is not available | CIS" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install dccp(\\s|$)" + line: "install dccp /bin/true" + create: true + mode: '0600' + + - name: "3.2.1 | PATCH | Ensure dccp kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist dccp(\\s|$)" + line: "blacklist dccp" + create: true + mode: '0600' -- name: "3.2.2 | PATCH | Ensure packet redirect sending is disabled" - ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' - sysctl_set: true - ignoreerrors: true - sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table - with_items: - - { name: net.ipv4.conf.all.send_redirects, value: 0 } - - { name: net.ipv4.conf.default.send_redirects, value: 0 } +- name: "3.2.2 | PATCH | Ensure tipc kernel module is not available" when: - - not rhel8cis_is_router - rhel8cis_rule_3_2_2 tags: - - level1-server - - level1-workstation + - level2-server + - level2-workstation - automated - patch - - sysctl + - tipc + - NIST800-53R5_CM-7 + - NIST800-53R5_SI-4 - rule_3.2.2 + + block: + - name: "3.2.2 | PATCH | Ensure tipc kernel module is not available | CIS" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install tipc(\\s|$)" + line: "install tipc /bin/true" + create: true + mode: '0600' + + - name: "3.2.2 | PATCH | Ensure tipc kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist tipc(\\s|$)" + line: "blacklist tipc" + create: true + mode: '0600' + +- name: "3.2.3 | PATCH | Ensure rds kernel module is not available" + when: + - rhel8cis_rule_3_2_3 + tags: + - level2-server + - level2-workstation + - automated + - patch + - rds + - NIST800-53R5_CM-7 + - NIST800-53R5_SI-4 + - rule_3.2.3 + block: + - name: "3.2.3 | PATCH | Ensure rds kernel module is not available | CIS" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install rpc(\\s|$)" + line: "install rds /bin/true" + create: true + mode: '0600' + + - name: "3.2.3 | PATCH | Ensure rds kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist rpc(\\s|$)" + line: "blacklist rds" + create: true + mode: '0600' + +- name: "3.2.4 | PATCH | Ensure sctp kernel module is not available" + when: + - rhel8cis_rule_3_2_4 + tags: + - level2-server + - level2-workstation + - automated + - patch + - sctp + - NIST800-53R5_CM-7 + - NIST800-53R5_SI-4 + - rule_3.2.4 + block: + - name: "3.2.4 | PATCH | Ensure sctp kernel module is not available | CIS" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install sctp(\\s|$)" + line: "install sctp /bin/true" + create: true + mode: '0600' + + - name: "3.2.4 | PATCH | Ensure sctp kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist sctp(\\s|$)" + line: "blacklist sctp" + create: true + mode: '0600' diff --git a/tasks/section_3/cis_3.3.x.yml b/tasks/section_3/cis_3.3.x.yml index 2d775d62..f54eaa6f 100644 --- a/tasks/section_3/cis_3.3.x.yml +++ b/tasks/section_3/cis_3.3.x.yml @@ -1,68 +1,44 @@ --- -- name: "3.3.1 | PATCH | Ensure source routed packets are not accepted" - block: - - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | Set routed packets IPv4" - ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' - sysctl_set: true - ignoreerrors: true - sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table - with_items: - - { name: net.ipv4.conf.all.accept_source_route, value: 0 } - - { name: net.ipv4.conf.default.accept_source_route, value: 0 } - - - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | Set routed packets IPv6" - ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' - sysctl_set: true - ignoreerrors: true - sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv6 route table - with_items: - - { name: net.ipv6.conf.all.accept_source_route, value: 0} - - { name: net.ipv6.conf.default.accept_source_route, value: 0 } - when: rhel8cis_ipv6_required or rhel8cis_ipv6_sysctl_force +- name: "3.3.1 | PATCH | Ensure IP forwarding is disabled" when: + - not rhel8cis_is_router - rhel8cis_rule_3_3_1 tags: - level1-server - level1-workstation - automated - - patch - sysctl + - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_3.3.1 - -- name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted" block: - - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | Set ICMP redirects IPv4" + - name: "3.3.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv4 forwarding" ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' - sysctl_set: true + name: net.ipv4.ip_forward + value: '0' ignoreerrors: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table - with_items: - - { name: net.ipv4.conf.all.accept_redirects, value: 0 } - - { name: net.ipv4.conf.default.accept_redirects, value: 0 } + notify: Sysctl_flush_ipv4_routes - - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | Set ICMP redirects IPv6" + - name: "3.3.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding" + when: + - rhel8cis_ipv6_required or + rhel8cis_ipv6_sysctl_force ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' - sysctl_set: true + name: net.ipv6.conf.all.forwarding + value: '0' ignoreerrors: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv6 route table - with_items: - - { name: net.ipv6.conf.all.accept_redirects, value: 0 } - - { name: net.ipv6.conf.default.accept_redirects, value: 0 } - when: rhel8cis_ipv6_required or rhel8cis_ipv6_sysctl_force + notify: Sysctl_flush_ipv6_routes + +- name: "3.3.2 | PATCH | Ensure packet redirect sending is disabled" when: + - not rhel8cis_is_router - rhel8cis_rule_3_3_2 tags: - level1-server @@ -70,19 +46,24 @@ - automated - patch - sysctl + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_3.3.2 - -- name: "3.3.3 | PATCH | Ensure secure ICMP redirects are not accepted" ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' + name: "{{ item.name }}" + value: "{{ item.value }}" sysctl_set: true ignoreerrors: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table - with_items: - - { name: net.ipv4.conf.all.secure_redirects, value: 0 } - - { name: net.ipv4.conf.default.secure_redirects, value: 0 } + notify: Sysctl_flush_ipv4_routes + loop: + - { name: net.ipv4.conf.all.send_redirects, value: 0 } + - { name: net.ipv4.conf.default.send_redirects, value: 0 } + +- name: "3.3.3 | PATCH | Ensure bogus ICMP responses are ignored" when: - rhel8cis_rule_3_3_3 tags: @@ -91,19 +72,21 @@ - automated - patch - sysctl + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_3.3.3 - -- name: "3.3.4 | PATCH | Ensure suspicious packets are logged" ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' - sysctl_set: true + name: net.ipv4.icmp_ignore_bogus_error_responses + value: '1' + state: present ignoreerrors: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table - with_items: - - { name: net.ipv4.conf.all.log_martians, value: 1 } - - { name: net.ipv4.conf.default.log_martians, value: 1 } + notify: Sysctl_flush_ipv4_routes + +- name: "3.3.4 | PATCH | Ensure broadcast ICMP requests are ignored" when: - rhel8cis_rule_3_3_4 tags: @@ -112,15 +95,21 @@ - automated - patch - sysctl + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_3.3.3 - rule_3.3.4 - -- name: "3.3.5 | PATCH | Ensure broadcast ICMP requests are ignored" ansible.posix.sysctl: name: net.ipv4.icmp_echo_ignore_broadcasts value: '1' ignoreerrors: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table + notify: Sysctl_flush_ipv4_routes + +- name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted" when: - rhel8cis_rule_3_3_5 tags: @@ -129,16 +118,39 @@ - automated - patch - sysctl + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_3.3.5 + block: + - name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted | Set ICMP redirects IPv4" + ansible.posix.sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + sysctl_set: true + ignoreerrors: true + sysctl_file: "{{ rhel8cis_sysctl_file }}" + notify: Sysctl_flush_ipv4_routes + loop: + - { name: net.ipv4.conf.all.accept_redirects, value: 0 } + - { name: net.ipv4.conf.default.accept_redirects, value: 0 } -- name: "3.3.6 | PATCH | Ensure bogus ICMP responses are ignored" - ansible.posix.sysctl: - name: net.ipv4.icmp_ignore_bogus_error_responses - value: '1' - state: present - ignoreerrors: true - sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table + - name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted | Set ICMP redirects IPv6" + when: rhel8cis_ipv6_required or rhel8cis_ipv6_sysctl_force + ansible.posix.sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + sysctl_set: true + ignoreerrors: true + sysctl_file: "{{ rhel8cis_sysctl_file }}" + notify: Sysctl_flush_ipv6_routes + loop: + - { name: net.ipv6.conf.all.accept_redirects, value: 0 } + - { name: net.ipv6.conf.default.accept_redirects, value: 0 } + +- name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted" when: - rhel8cis_rule_3_3_6 tags: @@ -147,9 +159,38 @@ - automated - patch - sysctl + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_3.3.6 + ansible.posix.sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + sysctl_set: true + ignoreerrors: true + sysctl_file: "{{ rhel8cis_sysctl_file }}" + notify: Sysctl_flush_ipv4_routes + loop: + - { name: net.ipv4.conf.all.secure_redirects, value: 0 } + - { name: net.ipv4.conf.default.secure_redirects, value: 0 } - name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled" + when: + - rhel8cis_rule_3_3_7 + tags: + - level1-server + - level1-workstation + - automated + - patch + - sysctl + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_3.3.7 ansible.posix.sysctl: name: "{{ item }}" value: '1' @@ -159,53 +200,117 @@ loop: - net.ipv4.conf.all.rp_filter - net.ipv4.conf.default.rp_filter - notify: sysctl flush ipv4 route table + notify: Sysctl_flush_ipv4_routes + +- name: "3.3.8 | PATCH | Ensure source routed packets are not accepted" when: - - rhel8cis_rule_3_3_7 + - rhel8cis_rule_3_3_8 tags: - level1-server - level1-workstation - automated - patch - sysctl - - rule_3.3.7 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_3.3.8 + block: + - name: "3.3.8 | PATCH | Ensure source routed packets are not accepted | Set routed packets IPv4" + ansible.posix.sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + sysctl_set: true + ignoreerrors: true + sysctl_file: "{{ rhel8cis_sysctl_file }}" + notify: Sysctl_flush_ipv4_routes + loop: + - { name: net.ipv4.conf.all.accept_source_route, value: 0 } + - { name: net.ipv4.conf.default.accept_source_route, value: 0 } + + - name: "3.3.8 | PATCH | Ensure source routed packets are not accepted | Set routed packets IPv6" + when: rhel8cis_ipv6_required or rhel8cis_ipv6_sysctl_force + ansible.posix.sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + sysctl_set: true + ignoreerrors: true + sysctl_file: "{{ rhel8cis_sysctl_file }}" + notify: Sysctl_flush_ipv6_routes + loop: + - { name: net.ipv6.conf.all.accept_source_route, value: 0} + - { name: net.ipv6.conf.default.accept_source_route, value: 0 } -- name: "3.3.8 | PATCH | Ensure TCP SYN Cookies is enabled" +- name: "3.3.9 | PATCH | Ensure suspicious packets are logged" + when: + - rhel8cis_rule_3_3_9 + tags: + - level1-server + - level1-workstation + - automated + - patch + - sysctl + - NIST800-53R5_AU-3 + - rule_3.3.9 ansible.posix.sysctl: - name: net.ipv4.tcp_syncookies - value: '1' + name: "{{ item.name }}" + value: "{{ item.value }}" sysctl_set: true ignoreerrors: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table + notify: Sysctl_flush_ipv4_routes + loop: + - { name: net.ipv4.conf.all.log_martians, value: 1 } + - { name: net.ipv4.conf.default.log_martians, value: 1 } + +- name: "3.3.10 | PATCH | Ensure TCP SYN Cookies is enabled" when: - - rhel8cis_rule_3_3_8 + - rhel8cis_rule_3_3_10 tags: - level1-server - level1-workstation - automated - patch - sysctl - - rule_3.3.8 - -- name: "3.3.9 | PATCH | Ensure IPv6 router advertisements are not accepted" + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_3.3.10 ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' + name: net.ipv4.tcp_syncookies + value: '1' sysctl_set: true ignoreerrors: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv6 route table - with_items: - - { name: net.ipv6.conf.all.accept_ra, value: 0 } - - { name: net.ipv6.conf.default.accept_ra, value: 0 } + notify: Sysctl_flush_ipv4_routes + +- name: "3.3.11 | PATCH | Ensure IPv6 router advertisements are not accepted" when: - rhel8cis_ipv6_required or rhel8cis_ipv6_sysctl_force - - rhel8cis_rule_3_3_9 + - rhel8cis_rule_3_3_11 tags: - level1-server - level1-workstation - automated - patch - sysctl - - rule_3.3.9 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_3.3.11 + ansible.posix.sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + sysctl_set: true + ignoreerrors: true + sysctl_file: "{{ rhel8cis_sysctl_file }}" + notify: Sysctl_flush_ipv6_routes + loop: + - { name: net.ipv6.conf.all.accept_ra, value: 0 } + - { name: net.ipv6.conf.default.accept_ra, value: 0 } diff --git a/tasks/section_3/cis_3.4.1.x.yml b/tasks/section_3/cis_3.4.1.x.yml index 8a20e276..1fe7c89f 100644 --- a/tasks/section_3/cis_3.4.1.x.yml +++ b/tasks/section_3/cis_3.4.1.x.yml @@ -1,152 +1,56 @@ --- -- name: "3.4.1.1 | PATCH | Ensure firewalld is installed" - ansible.builtin.package: - name: - - firewalld - - iptables - state: present +- name: "3.4.1.1 | PATCH | Ensure nftables is installed" when: - rhel8cis_rule_3_4_1_1 - - rhel8cis_firewall == "firewalld" + - "'nftables' not in ansible_facts.packages" tags: - level1-server - level1-workstation - - automated - patch - - firewalld + - nftables + - NIST800-53R5_CA-9 - rule_3.4.1.1 + ansible.builtin.package: + name: + - nftables + state: present -- name: "3.4.1.2 | PATCH | Ensure iptables-services not installed with firewalld" - block: - - name: "3.4.1.2 | PATCH | Ensure iptables-services not installed with firewalld | Stop running services" - ansible.builtin.systemd: - name: "{{ item }}" - masked: true - with_items: - - iptables - - ip6tables - when: item in ansible_facts.packages - - - name: "3.4.1.2 | PATCH | Ensure iptables-services not installed with firewalld | Remove IPTables" - ansible.builtin.package: - name: iptables-services - state: absent +- name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use" when: - rhel8cis_rule_3_4_1_2 - - rhel8cis_firewall == "firewalld" tags: - level1-server - level1-workstation - - automated - patch - firewalld + - nftables - rule_3.4.1.2 - -- name: "3.4.1.3 | PATCH | Ensure nftables either not installed or masked with firewalld" - ansible.builtin.systemd: - name: nftables - state: stopped - masked: true - when: - - rhel8cis_firewall == "firewalld" - - rhel8cis_rule_3_4_1_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - firewalld - - rule_3_4_1_3 - -- name: "3.4.1.4 | PATCH | Ensure firewalld service is enabled and running" - ansible.builtin.systemd: - name: firewalld - state: started - enabled: true - when: - - rhel8cis_firewall == "firewalld" - - rhel8cis_rule_3_4_1_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - firewalld - - rule_3_4_1_4 - -- name: "3.4.1.5 | PATCH | Ensure firewalld default zone is set" block: - - name: "3.4.1.5 | AUDIT | Ensure firewalld default zone is set" - ansible.builtin.shell: "firewall-cmd --get-default-zone | grep {{ rhel8cis_default_zone }}" - changed_when: false - failed_when: ( firewalld_zone_set.rc not in [ 0, 1 ] ) - register: firewalld_zone_set - - - name: "3.4.1.5 | AUDIT | Ensure firewalld default zone is set" - ansible.builtin.shell: firewall-cmd --set-default-zone="{{ rhel8cis_default_zone }}" + - name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | nftables" when: - - firewalld_zone_set.rc != 0 - when: - - rhel8cis_firewall == "firewalld" - - rhel8cis_rule_3_4_1_5 - tags: - - level1-server - - level1-workstation - - automated - - patch - - firewalld - - rule_3.4.1.5 - -- name: "3.4.1.6 | AUDIT | Ensure network interfaces are assigned to appropriate zone" - block: - - name: "3.4.1.6 | AUDIT | Ensure network interfaces are assigned to appropriate zone | Get list of interfaces and policies" - ansible.builtin.shell: "nmcli -t connection show | awk -F: '{ if($4){print $4} }' | while read INT; do firewall-cmd --get-active-zones | grep -B1 $INT; done" - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_3_4_1_6_interfacepolicy - - - name: "3.4.1.6 | AUDIT | Ensure network interfaces are assigned to appropriate zone | Get list of interfaces and policies | Show the interface to policy" - ansible.builtin.debug: - msg: - - "Warning!! The items below are the policies tied to the interfaces, please correct as needed" - - "{{ rhel8cis_3_4_1_6_interfacepolicy.stdout_lines }}" + - "'firewalld' in ansible_facts.packages" + - rhel8cis_firewall == "nftables" + ansible.builtin.systemd: + name: firewalld + masked: true - - name: "3.4.1.6 | AUDIT | Ensure network interfaces are assigned to appropriate zone | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '3.4.1.6' - when: - - rhel8cis_firewall == "firewalld" - - rhel8cis_rule_3_4_1_6 - tags: - - level1-server - - level1-workstation - - manual - - audit - - rule_3.4.1.6 + - name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | firewalld" + when: + - "'nftables' in ansible_facts.packages" + - rhel8cis_firewall == "firewalld" + ansible.builtin.systemd: + name: nftables + masked: true -- name: "3.4.1.7 | AUDIT | Ensure firewalld drops unnecessary services and ports" - block: - - name: "3.4.1.7 | AUDIT | Ensure firewalld drops unnecessary services and ports | Get list of services and ports" - ansible.builtin.shell: "firewall-cmd --get-active-zones | awk '!/:/ {print $1}' | while read ZN; do firewall-cmd --list-all --zone=$ZN; done" - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_3_4_1_7_servicesport + - name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | {{ rhel8cis_firewall }} package installed" + when: "rhel8cis_firewall not in ansible_facts.packages" + ansible.builtin.package: + name: "{{ rhel8cis_firewall }}" + state: present - - name: "3.4.1.7 | AUDIT | Ensure firewalld drops unnecessary services and ports | Show services and ports" - ansible.builtin.debug: - msg: - - "The items below are the services and ports that are accepted, please correct as needed" - - "{{ rhel8cis_3_4_1_7_servicesport.stdout_lines }}" - when: - - rhel8cis_firewall == "firewalld" - - rhel8cis_rule_3_4_1_7 - tags: - - level1-server - - level1-workstation - - manual - - audit - - rule_3.4.1.7 + - name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | {{ rhel8cis_firewall }} started and enabled" + ansible.builtin.systemd: + name: "{{ rhel8cis_firewall }}" + enabled: true + state: started diff --git a/tasks/section_3/cis_3.4.2.x.yml b/tasks/section_3/cis_3.4.2.x.yml index be9f79f4..2be48415 100644 --- a/tasks/section_3/cis_3.4.2.x.yml +++ b/tasks/section_3/cis_3.4.2.x.yml @@ -1,350 +1,238 @@ --- -- name: "3.4.2.1 | PATCH | Ensure nftables is installed" - ansible.builtin.package: - name: nftables - state: present +- name: "3.4.2.1 | PATCH | Ensure nftables base chains exist" when: - rhel8cis_firewall == "nftables" - rhel8cis_rule_3_4_2_1 tags: - level1-server - level1-workstation - - automated - patch - nftables + - NIST800-53R5_CA-9 - rule_3.4.2.1 - -# The control allows the service it be masked or not installed -# We have chosen not installed -- name: "3.4.2.2 | PATCH | Ensure firewalld is either not installed or masked with nftables" - ansible.builtin.package: - name: firewalld - state: absent - when: - - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - nftables - - rule_3.4.2.2 - -- name: "3.4.2.3 | PATCH | Ensure iptables-services not installed with nftables" - block: - - name: "3.4.2.3 | PATCH | Ensure iptables-services not installed with nftables | Stop services" - ansible.builtin.systemd: - name: "{{ item }}" - enabled: false - masked: true - ignore_errors: true # noqa ignore-errors - with_items: - - iptables - - ip6tables - - - name: "3.4.2.3 | PATCH | Ensure iptables-services not installed with nftables | Remove IPTables" - ansible.builtin.package: - name: iptables-service - state: absent - when: - - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - nftables - - rule_3.4.2.3 - -- name: "3.4.2.4 | PATCH | Ensure iptables are flushed with nftables" - block: - - name: "3.4.2.4 | PATCH | Ensure iptables are flushed with nftables | IPv4" - ansible.builtin.shell: iptables -F - - - name: "3.4.2.4 | PATCH | Ensure iptables are flushed with nftables | IPv6" - ansible.builtin.shell: ip6tables -F - when: rhel8cis_ipv6_required - when: - - rhel8cis_rule_3_4_2_4 - - rhel8cis_firewall != "firewalld" - tags: - - level1-server - - level1-workstation - - manual - - patch - - nftables - - rule_3.4.2.4 - -- name: "3.4.2.5 | AUDIT | Ensure an nftables table exists" - block: - - name: "3.4.2.5 | AUDIT | Ensure a table exists | Check for tables" - ansible.builtin.shell: nft list tables - changed_when: false - failed_when: false - register: rhel8cis_3_4_2_5_nft_tables - - - name: "3.4.2.5 | AUDIT | Ensure an nftables table exists | Show existing tables" - ansible.builtin.debug: - msg: - - "Below are the current nft tables, please review" - - "{{ rhel8cis_3_4_2_5_nft_tables.stdout_lines }}" - when: rhel8cis_3_4_2_5_nft_tables.stdout | length > 0 - - - name: "3.4.2.5 | AUDIT | Ensure an nftables table exists | Alert on no tables" - ansible.builtin.debug: - msg: - - "Warning!! You currently have no nft tables, please review your setup" - - 'Use the command "nft create table inet " to create a new table' - when: - - rhel8cis_3_4_2_5_nft_tables.stdout | length == 0 - - not rhel8cis_nft_tables_autonewtable - - - name: "3.4.2.5 | AUDIT | Ensure an nftables table exists| Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '3.4.2.5' - when: - - rhel8cis_3_4_2_5_nft_tables.stdout | length == 0 - - not rhel8cis_nft_tables_autonewtable - - - name: "3.4.2.5 | PATCH | Ensure a table exists | Create table if needed" - ansible.builtin.shell: nft create table inet "{{ rhel8cis_nft_tables_tablename }}" - failed_when: false - when: rhel8cis_nft_tables_autonewtable - when: - - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_5 - tags: - - level1-server - - level1-workstation - - automated - - patch - - nftables - - rule_3.4.2.5 - -- name: "3.4.2.6 | PATCH | Ensure nftables base chains exist" block: - - name: "3.4.2.6 | AUDIT | Ensure nftables base chains exist | Get current chains for INPUT" + - name: "3.4.2.1 | AUDIT | Ensure nftables base chains exist | Get current chains for INPUT" ansible.builtin.shell: nft list ruleset | grep 'hook input' changed_when: false failed_when: false - register: rhel8cis_3_4_2_6_input_chains + register: rhel8cis_3_4_2_1_input_chains - - name: "3.4.2.6 | AUDIT | Ensure nftables base chains exist | Get current chains for FORWARD" + - name: "3.4.2.1 | AUDIT | Ensure nftables base chains exist | Get current chains for FORWARD" ansible.builtin.shell: nft list ruleset | grep 'hook forward' changed_when: false failed_when: false - register: rhel8cis_3_4_2_6_forward_chains + register: rhel8cis_3_4_2_1_forward_chains - - name: "3.4.2.6 | AUDIT | Ensure nftables base chains exist | Get current chains for OUTPUT" + - name: "3.4.2.1 | AUDIT | Ensure nftables base chains exist | Get current chains for OUTPUT" ansible.builtin.shell: nft list ruleset | grep 'hook output' changed_when: false failed_when: false - register: rhel8cis_3_4_2_6_output_chains + register: rhel8cis_3_4_2_1_output_chains - - name: "3.4.2.6 | AUDIT | Ensure nftables base chains exist | Display chains for review" + - name: "3.4.2.1 | AUDIT | Ensure nftables base chains exist | Display chains for review" ansible.builtin.debug: msg: - "Below are the current INPUT chains" - - "{{ rhel8cis_3_4_2_6_input_chains.stdout_lines }}" + - "{{ rhel8cis_3_4_2_1_input_chains.stdout_lines }}" - "Below are the current FORWARD chains" - - "{{ rhel8cis_3_4_2_6_forward_chains.stdout_lines }}" + - "{{ rhel8cis_3_4_2_1_forward_chains.stdout_lines }}" - "Below are teh current OUTPUT chains" - - "{{ rhel8cis_3_4_2_6_output_chains.stdout_lines }}" + - "{{ rhel8cis_3_4_2_1_output_chains.stdout_lines }}" when: not rhel8cis_nft_tables_autochaincreate - - name: "3.4.2.6 | PATCH | Ensure nftables base chains exist | Create chains if needed" + - name: "3.4.2.1 | PATCH | Ensure nftables base chains exist | Create chains if needed" ansible.builtin.shell: "{{ item }}" failed_when: false - with_items: + loop: - nft create chain inet "{{ rhel8cis_nft_tables_tablename }}" input { type filter hook input priority 0 \; } - nft create chain inet "{{ rhel8cis_nft_tables_tablename }}" forward { type filter hook forward priority 0 \; } - nft create chain inet "{{ rhel8cis_nft_tables_tablename }}" output { type filter hook output priority 0 \; } when: rhel8cis_nft_tables_autochaincreate + +- name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured" when: - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_6 + - rhel8cis_rule_3_4_2_2 tags: - level1-server - level1-workstation - - automate - patch - nftables - - rule_3.4.2.6 - -- name: "3.4.2.7 | PATCH | Ensure nftables loopback traffic is configured" + - NIST800-53R5_CA-9 + - rule_3.4.2.2 block: - - name: "3.4.2.7 | AUDIT | Ensure nftables loopback traffic is configured | Gather iif lo accept existence" + - name: "3.4.2.2 | AUDIT | Ensure host based firewall loopback traffic is configured | Gather iif lo accept existence | nftables" ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'iif "lo" accept' changed_when: false failed_when: false - register: rhel8cis_3_4_2_7_iiflo + register: rhel8cis_3_4_2_2_iiflo - - name: "3.4.2.7 | AUDIT | Ensure nftables loopback traffic is configured | Gather ip saddr existence" + - name: "3.4.2.2 | AUDIT | Ensure host based firewall loopback traffic is configured | Gather ip saddr existence | nftables" ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip saddr' changed_when: false failed_when: false - register: rhel8cis_3_4_2_7_ipsaddr + register: rhel8cis_3_4_2_2_ipsaddr - - name: "3.4.2.7 | AUDIT | Ensure nftables loopback traffic is configured | Gather ip6 saddr existence" + - name: "3.4.2.2 | AUDIT | Ensure host based firewall loopback traffic is configured | Gather ip6 saddr existence | nftables" ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip6 saddr' changed_when: false failed_when: false - register: rhel8cis_3_4_2_7_ip6saddr + register: rhel8cis_3_4_2_2_ip6saddr - - name: "3.4.2.7 | PATCH | Ensure nftables loopback traffic is configured | Set iif lo accept rule" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input iif lo accept - when: '"iif \"lo\" accept" not in rhel8cis_3_4_2_7_iiflo.stdout' + - name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | Set iif lo accept rule | nftables" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input iif lo accept + when: '"iif \"lo\" accept" not in rhel8cis_3_4_2_2_iiflo.stdout' - - name: "3.4.2.7 | PATCH | Ensure nftables loopback traffic is configured | Set ip sddr rule" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip saddr 127.0.0.0/8 counter drop - when: '"ip saddr 127.0.0.0/8 counter packets 0 bytes 0 drop" not in rhel8cis_3_4_2_7_ipsaddr.stdout' + - name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | Set ip sddr rule | nftables" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip saddr 127.0.0.0/8 counter drop + when: '"ip saddr 127.0.0.0/8 counter packets 0 bytes 0 drop" not in rhel8cis_3_4_2_2_ipsaddr.stdout' - - name: "3.4.2.7 | PATCH | Ensure nftables loopback traffic is configured | Set ip6 saddr rule" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip6 saddr ::1 counter drop - when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in rhel8cis_3_4_2_7_ip6saddr.stdout' + - name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | Set ip6 saddr rule | nftables" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip6 saddr ::1 counter drop + when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in rhel8cis_3_4_2_4_ip6saddr.stdout' + +- name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | firewalld" when: - - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_7 + - rhel8cis_firewall == "firewalld" + - rhel8cis_rule_3_4_2_4 tags: - level1-server - level1-workstation - - automated - patch - nftables - - rule_3.4.2.7 + - NIST800-53R5_CA-9 + - rule_3.4.2.2 + ansible.posix.firewalld: + rich_rule: "{{ item }}" + zone: "{{ rhel8cis_default_zone }}" + permanent: true + immediate: true + state: enabled + loop: + - rule family="ipv4" source address="127.0.0.1" destination not address="127.0.0.1" drop + - rule family="ipv6" source address="::1" destination not address="::1" drop + +- name: "3.4.2.3 | AUDIT | Ensure firewalld drops unnecessary services and ports" + when: + - rhel8cis_firewall == "firewalld" + - rhel8cis_rule_3_4_2_3 + tags: + - level1-server + - level1-workstation + - manual + - audit + - NIST800-53R5_CA-9 + - rule_3.4.2.3 + block: + - name: "3.4.2.3 | AUDIT | Ensure firewalld drops unnecessary services and ports | Get list of services and ports" + ansible.builtin.shell: "firewall-cmd --get-active-zones | awk '!/:/ {print $1}' | while read ZN; do firewall-cmd --list-all --zone=$ZN; done" + changed_when: false + failed_when: false + check_mode: false + register: rhel8cis_3_4_2_3_servicesport -- name: "3.4.2.8 | PATCH | Ensure nftables outbound and established connections are configured" + - name: "3.4.2.3 | AUDIT | Ensure firewalld drops unnecessary services and ports | Show services and ports" + ansible.builtin.debug: + msg: + - "The items below are the services and ports that are accepted, please correct as needed" + - "{{ rhel8cis_3_4_2_3_servicesport.stdout_lines }}" + +- name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured" + when: + - rhel8cis_firewall == "nftables" + - rhel8cis_rule_3_4_2_4 + tags: + - level1-server + - level1-workstation + - patch + - nftables + - rule_3.4.2.4 block: - - name: "3.4.2.8 | AUDIT | Ensure nftables outbound and established connections are configured | Gather incoming connection rules" + - name: "3.4.2.4 | AUDIT | Ensure nftables established connections are configured | Gather incoming connection rules" ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state' changed_when: false failed_when: false - register: rhel8cis_3_4_2_8_inconnectionrule + register: rhel8cis_3_4_2_4_inconnectionrule - - name: "3.4.2.8 | AUDIT | Ensure nftables outbound and established connections are configured | Gather outbound connection rules" + - name: "3.4.2.4| AUDIT | Ensure nftables established connections are configured | Gather outbound connection rules" ansible.builtin.shell: nft list ruleset | awk '/hook output/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state' changed_when: false failed_when: false - register: rhel8cis_3_4_2_8_outconnectionrule + register: rhel8cis_3_4_2_4_outconnectionrule + + - name: "3.4.2.4| PATCH | Ensure nftables established connections are configured | Add input tcp established accept policy" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept + when: '"ip protocol tcp ct state established accept" not in rhel8cis_3_4_2_4_inconnectionrule.stdout' - - name: "3.4.2.8 | PATCH | Ensure nftables outbound and established connections are configured | Add input tcp established accept policy" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept - when: '"ip protocol tcp ct state established accept" not in rhel8cis_3_4_2_8_inconnectionrule.stdout' + - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add input udp established accept policy" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol udp ct state established accept + when: '"ip protocol udp ct state established accept" not in rhel8cis_3_4_2_4_inconnectionrule.stdout' - - name: "3.4.2.8 | PATCH | Ensure nftables outbound and established connections are configured | Add input udp established accept policy" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol udp ct state established accept - when: '"ip protocol udp ct state established accept" not in rhel8cis_3_4_2_8_inconnectionrule.stdout' + - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add input icmp established accept policy" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol icmp ct state established accept + when: '"ip protocol icmp ct state established accept" not in rhel8cis_3_4_2_4_inconnectionrule.stdout' - - name: "3.4.2.8 | PATCH | Ensure nftables outbound and established connections are configured | Add input icmp established accept policy" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol icmp ct state established accept - when: '"ip protocol icmp ct state established accept" not in rhel8cis_3_4_2_8_inconnectionrule.stdout' + - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add output tcp new, related, established accept policy" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol tcp ct state new,related,established accept + when: '"ip protocol tcp ct state established,related,new accept" not in rhel8cis_3_4_2_4_outconnectionrule.stdout' - - name: "3.4.2.8 | PATCH | Ensure nftables outbound and established connections are configured | Add output tcp new, related, established accept policy" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol tcp ct state new,related,established accept - when: '"ip protocol tcp ct state established,related,new accept" not in rhel8cis_3_4_2_8_outconnectionrule.stdout' + - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add output udp new, related, established accept policy" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol udp ct state new,related,established accept + when: '"ip protocol udp ct state established,related,new accept" not in rhel8cis_3_4_2_4_outconnectionrule.stdout' - - name: "3.4.2.8 | PATCH | Ensure nftables outbound and established connections are configured | Add output udp new, related, established accept policy" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol udp ct state new,related,established accept - when: '"ip protocol udp ct state established,related,new accept" not in rhel8cis_3_4_2_8_outconnectionrule.stdout' + - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add output icmp new, related, established accept policy" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol icmp ct state new,related,established accept + when: '"ip protocol icmp ct state established,related,new accept" not in rhel8cis_3_4_2_4_outconnectionrule.stdout' - - name: "3.4.2.8 | PATCH | Ensure nftables outbound and established connections are configured | Add output icmp new, related, established accept policy" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol icmp ct state new,related,established accept - when: '"ip protocol icmp ct state established,related,new accept" not in rhel8cis_3_4_2_8_outconnectionrule.stdout' +- name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy" when: - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_8 + - rhel8cis_rule_3_4_2_5 tags: - level1-server - level1-workstation - - automated - patch - nftables - - rule_3.4.3.8 - -- name: "3.4.2.9 | PATCH | Ensure nftables default deny firewall policy" + - NIST800-53R5_CA-9 + - rule_3.4.2.5 block: - - name: "3.4.2.9 | AUDIT | Ensure nftables default deny firewall policy | Check for hook input deny policy" + - name: "3.4.2.5 | AUDIT | Ensure nftables default deny firewall policy | Check for hook input deny policy" ansible.builtin.shell: nft list table inet "{{ rhel8cis_nft_tables_tablename }}" | grep 'hook input' failed_when: false changed_when: false - register: rhel8cis_3_4_2_9_inputpolicy + register: rhel8cis_3_4_2_5_inputpolicy - - name: "3.4.2.9 | AUDIT | Ensure nftables default deny firewall policy | Check for hook forward deny policy" + - name: "3.4.2.5 | AUDIT | Ensure nftables default deny firewall policy | Check for hook forward deny policy" ansible.builtin.shell: nft list table inet "{{ rhel8cis_nft_tables_tablename }}" | grep 'hook forward' failed_when: false changed_when: false - register: rhel8cis_3_4_2_9_forwardpolicy + register: rhel8cis_3_4_2_5_forwardpolicy - - name: "3.4.2.9 | AUDIT | Ensure nftables default deny firewall policy | Check for hook output deny policy" + - name: "3.4.2.5 | AUDIT | Ensure nftables default deny firewall policy | Check for hook output deny policy" ansible.builtin.shell: nft list table inet "{{ rhel8cis_nft_tables_tablename }}" | grep 'hook output' failed_when: false changed_when: false - register: rhel8cis_3_4_2_9_outputpolicy + register: rhel8cis_3_4_2_5_outputpolicy - - name: "3.4.2.9 | AUDIT | Ensure nftables default deny firewall policy | Check for SSH allow" + - name: "3.4.2.5 | AUDIT | Ensure nftables default deny firewall policy | Check for SSH allow" ansible.builtin.shell: nft list table inet "{{ rhel8cis_nft_tables_tablename }}" | grep 'ssh' failed_when: false changed_when: false - register: rhel8cis_3_4_2_9_sshallowcheck - - - name: "3.4.2.9 | PATCH | Ensure nftables default deny firewall policy | Enable SSH traffic" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input tcp dport ssh accept - when: '"tcp dport ssh accept" not in rhel8cis_3_4_2_9_sshallowcheck.stdout' - - - name: "3.4.2.9 | PATCH | Ensure nftables default deny firewall policy | Set hook input deny policy" - ansible.builtin.shell: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" input { policy drop \; } - when: '"type filter hook input priority 0; policy drop;" not in rhel8cis_3_4_2_9_inputpolicy.stdout' + register: rhel8cis_3_4_2_5_sshallowcheck - - name: "3.4.2.9 | PATCH | Ensure nftables default deny firewall policy | Create hook forward deny policy" - ansible.builtin.shell: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" forward { policy drop \; } - when: '"type filter hook forward priority 0; policy drop;" not in rhel8cis_3_4_2_9_forwardpolicy.stdout' + - name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy | Enable SSH traffic" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input tcp dport ssh accept + when: '"tcp dport ssh accept" not in rhel8cis_3_4_2_5_sshallowcheck.stdout' - - name: "3.4.2.9 | PATCH | Ensure nftables default deny firewall policy | Create hook output deny policy" - ansible.builtin.shell: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" output { policy drop \; } - when: '"type filter hook output priority 0; policy drop;" not in rhel8cis_3_4_2_9_outputpolicy.stdout' - when: - - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_9 - tags: - - level1-server - - level1-workstation - - automated - - patch - - nftables - - rule_3.4.2.9 + - name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy | Set hook input deny policy" + ansible.builtin.command: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" input { policy drop \; } + when: '"type filter hook input priority 0; policy drop;" not in rhel8cis_3_4_2_5_inputpolicy.stdout' -- name: "3.4.2.10 | PATCH | Ensure nftables service is enabled" - ansible.builtin.service: - name: nftables - enabled: true - when: - - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_10 - tags: - - level1-server - - level1-workstation - - automated - - patch - - nftables - - rule_3.4.3.10 + - name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy | Create hook forward deny policy" + ansible.builtin.command: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" forward { policy drop \; } + when: '"type filter hook forward priority 0; policy drop;" not in rhel8cis_3_4_2_5_forwardpolicy.stdout' -- name: "3.4.2.11 | PATCH | Ensure nftables rules are permanent" - ansible.builtin.lineinfile: - path: /etc/sysconfig/nftables.conf - state: present - insertafter: EOF - line: include "/etc/nftables/inet-{{ rhel8cis_nft_tables_tablename }}" - when: - - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_11 - tags: - - level1-server - - level1-workstation - - automated - - patch - - nftables - - rule_3.4.2.11 + - name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy | Create hook output deny policy" + ansible.builtin.command: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" output { policy drop \; } + when: '"type filter hook output priority 0; policy drop;" not in rhel8cis_3_4_2_5_outputpolicy.stdout' diff --git a/tasks/section_3/cis_3.4.3.1.x.yml b/tasks/section_3/cis_3.4.3.1.x.yml deleted file mode 100644 index 37c21775..00000000 --- a/tasks/section_3/cis_3.4.3.1.x.yml +++ /dev/null @@ -1,50 +0,0 @@ ---- - -- name: "3.4.3.1.1 | PATCH | Ensure iptables packages are installed" - ansible.builtin.package: - name: - - iptables - - iptables-services - state: present - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_1_1 - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.1.1 - -- name: "3.4.3.1.2 | PATCH | Ensure nftables is not installed with iptables" - ansible.builtin.package: - name: nftables - state: absent - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_1_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.1.2 - -# The control allows the service it be masked or not installed -# We have chosen not installed -- name: "3.4.3.1.3 | PATCH | Ensure firewalld is either not installed or masked with iptables" - ansible.builtin.package: - name: firewalld - state: absent - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_1_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.1.3 diff --git a/tasks/section_3/cis_3.4.3.2.x.yml b/tasks/section_3/cis_3.4.3.2.x.yml deleted file mode 100644 index 1d7bf337..00000000 --- a/tasks/section_3/cis_3.4.3.2.x.yml +++ /dev/null @@ -1,169 +0,0 @@ ---- - -- name: "3.4.3.2.1 | PATCH | Ensure iptables loopback traffic is configured" - block: - - name: "3.4.3.2.1 | PATCH | Ensure iptables loopback traffic is configured | INPUT Loopback ACCEPT" - ansible.builtin.iptables: - action: append - chain: INPUT - in_interface: lo - jump: ACCEPT - - - name: "3.4.3.2.1 | PATCH | Ensure iptables loopback traffic is configured | OUTPUT Loopback ACCEPT" - ansible.builtin.iptables: - action: append - chain: OUTPUT - out_interface: lo - jump: ACCEPT - - - name: "3.4.3.2.1 | PATCH | Ensure iptables loopback traffic is configured | INPUT Loopback 127.0.0.0/8" - ansible.builtin.iptables: - action: append - chain: INPUT - source: 127.0.0.0/8 - jump: DROP - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_2_1 - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.2.1 - -- name: "3.4.3.2.2 | PATCH | Ensure iptables outbound and established connections are configured" - ansible.builtin.iptables: - action: append - chain: '{{ item.chain }}' - protocol: '{{ item.protocol }}' - match: state - ctstate: '{{ item.ctstate }}' - jump: ACCEPT - with_items: - - { chain: OUTPUT, protocol: tcp, ctstate: 'NEW,ESTABLISHED' } - - { chain: OUTPUT, protocol: udp, ctstate: 'NEW,ESTABLISHED' } - - { chain: OUTPUT, protocol: icmp, ctstate: 'NEW,ESTABLISHED' } - - { chain: INPUT, protocol: tcp, ctstate: ESTABLISHED } - - { chain: INPUT, protocol: udp, ctstate: ESTABLISHED } - - { chain: INPUT, protocol: icmp, ctstate: ESTABLISHED } - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_2_2 - tags: - - level1-server - - level1-workstation - - manual - - patch - - iptables - - rule_3.4.3.2.2 - -- name: "3.4.3.2.3 | PATCH | Ensure iptables rules exist for all open ports" - block: - - name: "3.4.3.2.3 | AUDIT | Ensure iptables rules exist for all open ports | Get list of TCP open ports" - ansible.builtin.shell: netstat -ant |grep "tcp.*LISTEN" | awk '{ print $4 }'| sed 's/.*://' - changed_when: false - failed_when: false - register: rhel8cis_3_4_3_2_3_otcp - - - name: "3.4.3.2.3 | AUDIT | Ensure iptables rules exist for all open ports | Get the list of udp open ports" - ansible.builtin.shell: netstat -ant |grep "udp.*LISTEN" | awk '{ print $4 }'| sed 's/.*://' - changed_when: false - failed_when: false - register: rhel8cis_3_4_3_2_3_oudp - - - name: "3.4.3.2.3 | PATCH | Ensure iptables rules exist for all open ports | Adjust open tcp ports" - ansible.builtin.iptables: - action: append - chain: INPUT - protocol: tcp - destination_port: "{{ item }}" - match: state - ctstate: NEW - jump: ACCEPT - with_items: - - "{{ rhel8cis_3_4_3_2_3_otcp.stdout_lines }}" - when: rhel8cis_3_4_3_2_3_otcp.stdout is defined - - - name: "3.4.3.2.3 | PATCH | Ensure iptables rules exist for all open ports | Adjust open udp ports" - ansible.builtin.iptables: - action: append - chain: INPUT - protocol: udp - destination_port: "{{ item }}" - match: state - ctstate: NEW - jump: ACCEPT - with_items: - - "{{ rhel8cis_3_4_3_2_3_oudp.stdout_lines }}" - when: rhel8cis_3_4_3_2_3_otcp.stdout is defined - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_2_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.2.3 - -- name: "3.4.3.2.4 | PATCH | Ensure iptables default deny firewall policy" - block: - - name: "3.4.3.2.4 | PATCH | Ensure iptables default deny firewall policy | Configure ssh to be allowed" - ansible.builtin.iptables: - chain: INPUT - protocol: tcp - destination_port: "22" - jump: ACCEPT - - - name: "3.4.3.2.4 | PATCH | Ensure iptables default deny firewall policy | Set drop items" - ansible.builtin.iptables: - policy: DROP - chain: "{{ item }}" - with_items: - - INPUT - - FORWARD - - OUTPUT - when: - - rhel8cis_rule_3_4_3_2_4 - - rhel8cis_firewall == "iptables" - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.2.4 - -- name: "3.4.3.2.5 | PATCH | Ensure iptables rules are saved" - community.general.iptables_state: - state: saved - path: /etc/sysconfig/iptables - when: - - rhel8cis_rule_3_4_3_2_5 - - rhel8cis_firewall == "iptables" - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.2.5 - -- name: "3.4.3.2.6 | PATCH | Ensure iptables service is enabled and active" - ansible.builtin.service: - name: iptables - enabled: true - state: started - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_2_6 - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.2.6 diff --git a/tasks/section_3/cis_3.4.3.3.x.yml b/tasks/section_3/cis_3.4.3.3.x.yml deleted file mode 100644 index 4bce1b99..00000000 --- a/tasks/section_3/cis_3.4.3.3.x.yml +++ /dev/null @@ -1,163 +0,0 @@ ---- - -- name: "3.4.3.3.1 | PATCH | Ensure ip6tables loopback traffic is configured" - block: - - name: "3.4.3.3.1 | PATCH | Ensure ip6tables loopback traffic is configured | INPUT Loopback ACCEPT" - ansible.builtin.iptables: - action: append - chain: INPUT - in_interface: lo - jump: ACCEPT - ip_version: ipv6 - - - name: "3.4.3.3.1 | PATCH | Ensure ip6tables loopback traffic is configured | OUTPUT Loopback ACCEPT" - ansible.builtin.iptables: - action: append - chain: OUTPUT - out_interface: lo - jump: ACCEPT - ip_version: ipv6 - - - name: "3.4.3.3.1 | PATCH | Ensure ip6tables loopback traffic is configured | INPUT Loopback 127.0.0.0/8" - ansible.builtin.iptables: - action: append - chain: INPUT - source: ::1 - jump: DROP - ip_version: ipv6 - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_3_1 - - rhel8cis_ipv6_required - tags: - - level1-server - - level1-workstation - - automated - - patch - - ip6tables - - rule_3.4.3.3.1 - -- name: "3.4.3.3.2 | PATCH | Ensure ip6tables outbound and established connections are configured" - ansible.builtin.iptables: - action: append - chain: '{{ item.chain }}' - protocol: '{{ item.protocol }}' - match: state - ctstate: '{{ item.ctstate }}' - jump: ACCEPT - ip_version: ipv6 - with_items: - - { chain: OUTPUT, protocol: tcp, ctstate: 'NEW,ESTABLISHED' } - - { chain: OUTPUT, protocol: udp, ctstate: 'NEW,ESTABLISHED' } - - { chain: OUTPUT, protocol: icmp, ctstate: 'NEW,ESTABLISHED' } - - { chain: INPUT, protocol: tcp, ctstate: ESTABLISHED } - - { chain: INPUT, protocol: udp, ctstate: ESTABLISHED } - - { chain: INPUT, protocol: icmp, ctstate: ESTABLISHED } - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_3_2 - - rhel8cis_ipv6_required - tags: - - level1-server - - level1-workstation - - manual - - patch - - ip6tables - - rule_3.4.3.3.2 - -- name: "3.4.3.3.3 | PATCH | Ensure ip6tables firewall rules exist for all open ports" - block: - - name: "3.4.3.3.3 | AUDIT | Ensure ip6tables firewall rules exist for all open ports | Get list of TCP6 open ports" - ansible.builtin.shell: netstat -ant |grep "tcp6.*LISTEN" | awk '{ print $4 }'| sed 's/.*://' - changed_when: false - failed_when: false - register: rhel8cis_3_4_3_3_3_otcp - - - name: "3.4.3.3.3 | PATCH |Ensure ip6tables firewall rules exist for all open ports| Adjust open tcp6 ports" - ansible.builtin.iptables: - action: append - chain: INPUT - protocol: tcp - destination_port: "{{ item }}" - match: state - ctstate: NEW - jump: ACCEPT - ip_version: ipv6 - with_items: - - "{{ rhel8cis_3_4_3_3_3_otcp.stdout_lines }}" - when: rhel8cis_3_4_3_3_3_otcp.stdout is defined - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_3_3 - - rhel8cis_ipv6_required - tags: - - level1-server - - level1-workstation - - automated - - patch - - ip6tables - - rule_3.4.3.3.3 - -- name: "3.4.3.3.4 | PATCH | Ensure ip6tables default deny firewall policy" - block: - - name: "3.4.3.3.4 | PATCH | Ensure ip6tables default deny firewall policy | Configure ssh to be allowed" - ansible.builtin.iptables: - chain: INPUT - protocol: tcp - destination_port: "22" - jump: ACCEPT - ip_version: ipv6 - - - name: "3.4.3.3.4 | PATCH | Ensure ip6tables default deny firewall policy | Set drop items" - ansible.builtin.iptables: - policy: DROP - chain: "{{ item }}" - ip_version: ipv6 - with_items: - - INPUT - - FORWARD - - OUTPUT - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_3_4 - - rhel8cis_ipv6_required - tags: - - level1-server - - level1-workstation - - automated - - patch - - ip6tables - - rule_3.4.3.3.4 - -- name: "3.4.3.3.5 | PATCH | Ensure ip6tables rules are saved" - community.general.iptables_state: - state: saved - path: /etc/sysconfig/ip6tables - ip_version: ipv6 - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_ipv6_required - - rhel8cis_rule_3_4_3_3_5 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ip6tables - - rule_3.4.3.3.5 - -- name: "3.4.3.3.6 | PATCH | Ensure ip6tables service is enabled and active" - ansible.builtin.service: - name: ip6tables - enabled: true - state: started - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_3_6 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ip6tables - - rule_3.4.3.3.6 diff --git a/tasks/section_3/main.yml b/tasks/section_3/main.yml index a62f56ef..42726685 100644 --- a/tasks/section_3/main.yml +++ b/tasks/section_3/main.yml @@ -1,35 +1,21 @@ --- -- name: "SECTION | 3.1.x | Disable unused network protocols and devices" - ansible.builtin.import_tasks: cis_3.1.x.yml +- name: "SECTION | 3.1.x | Configure network devices" + ansible.builtin.import_tasks: + file: cis_3.1.x.yml -- name: "SECTION | 3.2.x | Network Parameters (Host Only)" - ansible.builtin.import_tasks: cis_3.2.x.yml +- name: "SECTION | 3.2.x | Network kernel modules" + ansible.builtin.import_tasks: + file: cis_3.2.x.yml -- name: "SECTION | 3.3.x | Network Parameters (Host and Router)" - ansible.builtin.import_tasks: cis_3.3.x.yml +- name: "SECTION | 3.3.x | Network kernel Parameters" + ansible.builtin.import_tasks: + file: cis_3.3.x.yml -- name: "SECTION | 3.4.1.x | Configure firewalld" - ansible.builtin.import_tasks: cis_3.4.1.x.yml - when: - - rhel8cis_firewall == "firewalld" +- name: "SECTION | 3.4.1.x | Configure firewall utility" + ansible.builtin.import_tasks: + file: cis_3.4.1.x.yml -- name: "SECTION | 3.4.2.x | Configure nftables" - ansible.builtin.import_tasks: cis_3.4.2.x.yml - when: - - rhel8cis_firewall == "nftables" - -- name: "SECTION | 3.4.3.1.x | Configure iptables software" - ansible.builtin.import_tasks: cis_3.4.3.1.x.yml - when: - - rhel8cis_firewall == "iptables" - -- name: "SECTION | 3.4.3.2.x | Configure IPv4 iptables" - ansible.builtin.import_tasks: cis_3.4.3.2.x.yml - when: - - rhel8cis_firewall == "iptables" - -- name: "SECTION | 3.4.3.3.x | Configure IPv6 iptables" - ansible.builtin.import_tasks: cis_3.4.3.3.x.yml - when: - - ( rhel8cis_firewall == "iptables" and rhel8cis_ipv6_required ) +- name: "SECTION | 3.4.2.x | Configure firewall rules" + ansible.builtin.import_tasks: + file: cis_3.4.2.x.yml diff --git a/tasks/section_4/cis_4.1.1.x.yml b/tasks/section_4/cis_4.1.1.x.yml index 6f486d8d..59aa8adb 100644 --- a/tasks/section_4/cis_4.1.1.x.yml +++ b/tasks/section_4/cis_4.1.1.x.yml @@ -1,109 +1,164 @@ --- -- name: "4.1.1.1 | PATCH | Ensure auditd is installed" - block: - - name: "4.1.1.1 | PATCH | Ensure auditd is installed | Install auditd packages" - ansible.builtin.package: - name: audit - state: present - when: '"auditd" not in ansible_facts.packages' - - - name: "4.1.1.1 | PATCH | Ensure auditd is installed | Install auditd-lib packages" - ansible.builtin.package: - name: audit-libs - state: present - when: '"auditd-lib" not in ansible_facts.packages' +- name: "4.1.1.1 | PATCH | Ensure cron daemon is enabled and active" when: - rhel8cis_rule_4_1_1_1 tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - automated - patch - - auditd + - cron + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_4.1.1.1 - -- name: "4.1.1.2 | PATCH | Ensure auditd service is enabled" - ansible.builtin.service: - name: auditd - state: started + ansible.builtin.systemd: + name: crond enabled: true + state: started + +- name: "4.1.1.2 | PATCH | Ensure permissions on /etc/crontab are configured" when: - rhel8cis_rule_4_1_1_2 tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - automated - patch - - auditd + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_4.1.1.2 + ansible.builtin.file: + path: /etc/crontab + owner: root + group: root + mode: '0600' -- name: "4.1.1.3 | PATCH | Ensure auditing for processes that start prior to auditd is enabled" - block: - - name: "4.1.1.3 | AUDIT | Ensure auditing for processes that start prior to auditd is enabled | Get GRUB_CMDLINE_LINUX" - ansible.builtin.shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//' - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_4_1_1_3_grub_cmdline_linux - - - name: "4.1.1.3 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Replace existing setting" - ansible.builtin.replace: - path: /etc/default/grub - regexp: 'audit=.' - replace: 'audit=1' - notify: rhel8cis_grub2cfg - when: "'audit=' in rhel8cis_4_1_1_3_grub_cmdline_linux.stdout" - - - name: "4.1.1.3 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Add audit setting if missing" - ansible.builtin.lineinfile: - path: /etc/default/grub - regexp: '^GRUB_CMDLINE_LINUX=' - line: '{{ rhel8cis_4_1_1_3_grub_cmdline_linux.stdout }} audit=1"' - notify: rhel8cis_grub2cfg - when: "'audit=' not in rhel8cis_4_1_1_3_grub_cmdline_linux.stdout" +- name: "4.1.1.3 | PATCH | Ensure permissions on /etc/cron.hourly are configured" when: - rhel8cis_rule_4_1_1_3 tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - automated - patch - - auditd - - grub + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_4.1.1.3 + ansible.builtin.file: + path: /etc/cron.hourly + state: directory + owner: root + group: root + mode: '0700' -- name: "4.1.1.4 | PATCH | Ensure audit_backlog_limit is sufficient" - block: - - name: "4.1.1.4 | AUDIT | Ensure audit_backlog_limit is sufficient | Get GRUB_CMDLINE_LINUX" - ansible.builtin.shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//' - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_4_1_1_4_grub_cmdline_linux - - - name: "4.1.1.4 | PATCH | Ensure audit_backlog_limit is sufficient | Replace existing setting" - ansible.builtin.replace: - path: /etc/default/grub - regexp: 'audit_backlog_limit=\d+' - replace: 'audit_backlog_limit={{ rhel8cis_audit_back_log_limit }}' - notify: rhel8cis_grub2cfg - when: "'audit_backlog_limit=' in rhel8cis_4_1_1_4_grub_cmdline_linux.stdout" - - - name: "4.1.1.4 | PATCH | Ensure audit_backlog_limit is sufficient | Add audit_backlog_limit setting if missing" - ansible.builtin.lineinfile: - path: /etc/default/grub - regexp: '^GRUB_CMDLINE_LINUX=' - line: '{{ rhel8cis_4_1_1_4_grub_cmdline_linux.stdout }} audit_backlog_limit={{ rhel8cis_audit_back_log_limit }}"' - notify: rhel8cis_grub2cfg - when: "'audit_backlog_limit=' not in rhel8cis_4_1_1_4_grub_cmdline_linux.stdout" +- name: "4.1.1.4 | PATCH | Ensure permissions on /etc/cron.daily are configured" when: - rhel8cis_rule_4_1_1_4 tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - automated - patch - - auditd - - grub + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_4.1.1.4 + ansible.builtin.file: + path: /etc/cron.daily + state: directory + owner: root + group: root + mode: '0700' + +- name: "4.1.1.5 | PATCH | Ensure permissions on /etc/cron.weekly are configured" + when: + - rhel8cis_rule_4_1_1_5 + tags: + - level1-server + - level1-workstation + - patch + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.1.1.5 + ansible.builtin.file: + path: /etc/cron.weekly + state: directory + owner: root + group: root + mode: '0700' + +- name: "4.1.1.6 | PATCH | Ensure permissions on /etc/cron.monthly are configured" + when: + - rhel8cis_rule_4_1_1_6 + tags: + - level1-server + - level1-workstation + - automated + - patch + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.1.1.6 + ansible.builtin.file: + path: /etc/cron.monthly + state: directory + owner: root + group: root + mode: '0700' + +- name: "4.1.1.7 | PATCH | Ensure permissions on /etc/cron.d are configured" + when: + - rhel8cis_rule_4_1_1_7 + tags: + - level1-server + - level1-workstation + - automated + - patch + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.1.1.7 + ansible.builtin.file: + path: /etc/cron.d + state: directory + owner: root + group: root + mode: 0700 + +- name: "4.1.1.8 | PATCH | Ensure cron is restricted to authorized users" + when: + - rhel8cis_rule_4_1_1_8 + tags: + - level1-server + - level1-workstation + - automated + - patch + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.1.1.8 + block: + - name: "4.1.1.8 | PATCH | Ensure cron is restricted to authorized users | Remove cron.deny" + ansible.builtin.file: + path: /etc/cron.deny + state: absent + + - name: "4.1.1.8 | PATCH | Ensure cron is restricted to authorized users | Check if cron.allow exists" + ansible.builtin.stat: + path: "/etc/cron.allow" + register: rhel8cis_4_1_1_8_cron_allow_state + + - name: "4.1.1.8 | PATCH | Ensure cron is restricted to authorized users | Ensure cron.allow is restricted to authorized users" + ansible.builtin.file: + path: /etc/cron.allow + state: '{{ "file" if rhel8cis_4_1_1_8_cron_allow_state.stat.exists else "touch" }}' + owner: root + group: root + mode: g-wx,o-rwx diff --git a/tasks/section_4/cis_4.1.2.x.yml b/tasks/section_4/cis_4.1.2.x.yml index dfca1af6..202c7f6c 100644 --- a/tasks/section_4/cis_4.1.2.x.yml +++ b/tasks/section_4/cis_4.1.2.x.yml @@ -1,53 +1,32 @@ --- -- name: "4.1.2.1 | PATCH | Ensure audit log storage size is configured" - ansible.builtin.lineinfile: - path: /etc/audit/auditd.conf - regexp: "^max_log_file( |=)" - line: "max_log_file = {{ rhel8cis_max_log_file_size }}" - notify: restart auditd +- name: "4.1.2.1 | PATCH | Ensure at is restricted to authorized users" when: - rhel8cis_rule_4_1_2_1 tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - automated - patch - - auditd + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_4.1.2.1 + block: + - name: "4.1.2.1 | PATCH | Ensure at is restricted to authorized users | Remove at.deny" + ansible.builtin.file: + path: /etc/at.deny + state: absent -- name: "4.1.2.2 | PATCH | Ensure audit logs are not automatically deleted" - ansible.builtin.lineinfile: - path: /etc/audit/auditd.conf - regexp: "^max_log_file_action" - line: "max_log_file_action = {{ rhel8cis_auditd['max_log_file_action'] }}" - notify: restart auditd - when: - - rhel8cis_rule_4_1_2_2 - tags: - - level2-server - - level2-workstation - - automated - - patch - - auditd - - rule_4.1.2.2 + - name: "4.1.2.1 | PATCH | Ensure at is restricted to authorized users | Check if at.allow exists" + ansible.builtin.stat: + path: "/etc/at.allow" + register: rhel8cis_4_1_2_1_at_allow_state -- name: "4.1.2.3 | PATCH | Ensure system is disabled when audit logs are full" - ansible.builtin.lineinfile: - path: /etc/audit/auditd.conf - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - notify: restart auditd - with_items: - - { regexp: '^admin_space_left_action', line: 'admin_space_left_action = {{ rhel8cis_auditd.admin_space_left_action }}' } - - { regexp: '^action_mail_acct', line: 'action_mail_acct = {{ rhel8cis_auditd.action_mail_acct }}' } - - { regexp: '^space_left_action', line: 'space_left_action = {{ rhel8cis_auditd.space_left_action }}' } - when: - - rhel8cis_rule_4_1_2_3 - tags: - - level2-server - - level2-workstation - - automated - - patch - - auditd - - rule_4.1.2.3 + - name: "4.1.2.1 | PATCH | Ensure at is restricted to authorized users | Ensure at.allow is restricted to authorized users" + ansible.builtin.file: + path: /etc/at.allow + state: '{{ "file" if rhel8cis_4_1_2_1_at_allow_state.stat.exists else "touch" }}' + owner: root + group: root + mode: 0600 diff --git a/tasks/section_4/cis_4.2.3.yml b/tasks/section_4/cis_4.2.3.yml deleted file mode 100644 index 0aa9f25a..00000000 --- a/tasks/section_4/cis_4.2.3.yml +++ /dev/null @@ -1,35 +0,0 @@ ---- - -- name: "4.2.3 | PATCH | Ensure permissions on all logfiles are configured" - block: - - name: "4.2.3 | AUDIT | Ensure permissions on all logfiles are configured | find files" - ansible.builtin.shell: find /var/log/ -type f -perm /g+wx,o+rwx -exec ls {} \; - changed_when: false - failed_when: false - register: rhel8cis_4_2_3_logfiles - - - name: "4.2.3 | AUDIT | Ensure permissions on all logfiles are configured | set_fact" - ansible.builtin.set_fact: - rhel8cis_4_2_3_logfiles_flattened: "{{ rhel8cis_4_2_3_logfiles | json_query('stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] - when: - - rhel8cis_4_2_3_logfiles.stdout_lines | length > 0 - - rhel8cis_4_2_3_logfiles is defined - - - name: "4.2.3 | PATCH | Ensure permissions on all logfiles are configured | change permissions" - ansible.builtin.file: - path: "{{ item }}" - mode: 0640 - loop: "{{ rhel8cis_4_2_3_logfiles_flattened }}" - when: - - rhel8cis_4_2_3_logfiles_flattened is defined - - item != "/var/log/btmp" - - item != "/var/log/utmp" - - item != "/var/log/wtmp" - when: - - rhel8cis_rule_4_2_3 - tags: - - level1-server - - level1-workstation - - patch - - logfiles - - rule_4.2.3 diff --git a/tasks/section_4/cis_4.2.x.yml b/tasks/section_4/cis_4.2.x.yml new file mode 100644 index 00000000..8e448d83 --- /dev/null +++ b/tasks/section_4/cis_4.2.x.yml @@ -0,0 +1,488 @@ +--- + +- name: "4.2.1 | Ensure permissions on /etc/ssh/sshd_config are configured" + when: + - rhel8cis_rule_4_2_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - permissions + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.2.1 + ansible.builtin.file: + path: /etc/ssh/sshd_config + owner: root + group: root + mode: '0600' + +- name: "4.2.2 | PATCH | Ensure permissions on SSH private host key files are configured" + when: + - rhel8cis_rule_4_2_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - permissions + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.2.2 + block: + - name: "4.2.2 | AUDIT | Ensure permissions on SSH private host key files are configured | Find the SSH private host keys" + ansible.builtin.find: + paths: /etc/ssh + patterns: 'ssh_host_*_key' + recurse: true + file_type: any + register: rhel8cis_4_2_2_ssh_private_host_key + + - name: "4.2.2 | PATCH | Ensure permissions on SSH private host key files are configured | Set permissions on SSH private host keys" + ansible.builtin.file: + path: "{{ item.path }}" + owner: root + group: root + mode: 0600 + loop: "{{ rhel8cis_4_2_2_ssh_private_host_key.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "4.2.3 | PATCH | Ensure permissions on SSH public host key files are configured" + when: + - rhel8cis_rule_4_2_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.2.3 + block: + - name: "4.2.3 | AUDIT | Ensure permissions on SSH public host key files are configured | Find the SSH public host keys" + ansible.builtin.find: + paths: /etc/ssh + patterns: 'ssh_host_*_key.pub' + recurse: true + file_type: any + register: rhel8cis_4_2_3_ssh_public_host_key + + - name: "4.2.3 | PATCH | Ensure permissions on SSH public host key files are configured | Set permissions on SSH public host keys" + ansible.builtin.file: + path: "{{ item.path }}" + owner: root + group: root + mode: 0644 + loop: "{{ rhel8cis_4_2_3_ssh_public_host_key.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "4.2.4 | PATCH | Ensure SSH access is configured" + when: + - rhel8cis_rule_4_2_4 + - rhel8cis_sshd_limited + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.2.4 + block: + - name: "4.2.4 | PATCH | Ensure SSH access is configured | Add line to sshd_config for allowusers" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^AllowUsers" + line: AllowUsers {{ rhel8cis_sshd['allowusers'] }} + notify: Restart_sshd + when: "rhel8cis_sshd['allowusers']|default('') | length > 0" + + - name: "4.2.4 | PATCH | Ensure SSH access is configured | Add line to sshd_config for allowgroups" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^AllowGroups" + line: AllowGroups {{ rhel8cis_sshd['allowgroups'] }} + notify: Restart_sshd + when: "rhel8cis_sshd['allowgroups']|default('') | length > 0" + + - name: "4.2.4 | PATCH | Ensure SSH access is configured | Add line to sshd_config for denyusers" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^DenyUsers" + line: DenyUsers {{ rhel8cis_sshd['denyusers'] }} + notify: Restart_sshd + when: "rhel8cis_sshd['denyusers']|default('') | length > 0" + + - name: "4.2.4 | PATCH | Ensure SSH access is configured | Add line to sshd_config for denygroups" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^DenyGroups" + line: DenyGroups {{ rhel8cis_sshd['denygroups'] }} + notify: Restart_sshd + when: "rhel8cis_sshd['denygroups']|default('') | length > 0" + +- name: "4.2.5 | PATCH | Ensure SSH warning banner is configured" + when: + - rhel8cis_rule_4_2_5 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.5 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: '^Banner' + line: 'Banner /etc/issue.net' + +- name: "4.2.6 | PATCH | Ensure sshd Ciphers are configured" + when: + - rhel8cis_rule_4_2_6 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - ciphers + - NIST800-53R5_SC-8 + - rule_4.2.6 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#Ciphers|^Ciphers" + line: "Ciphers {{ rhel8cis_sshd['ciphers'] }}" + +- name: "4.2.7 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured" + when: + - rhel8cis_rule_4_2_7 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.7 + block: + - name: "4.2.7 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured | Add line in sshd_config for ClientAliveInterval" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: '^ClientAliveInterval' + line: "ClientAliveInterval {{ rhel8cis_sshd['clientaliveinterval'] }}" + + - name: "4.2.7 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured | Ensure SSH ClientAliveCountMax set to <= 3" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: '^ClientAliveCountMax' + line: "ClientAliveCountMax {{ rhel8cis_sshd['clientalivecountmax'] }}" + +- name: "4.2.8 | PATCH | Ensure sshd DisableForwarding is enabled" + when: + - rhel8cis_rule_4_2_8 + tags: + - level2-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-7 + - rule_4.2.8 + block: + - name: "4.2.8 | PATCH | Ensure sshd DisableForwarding is enabled" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#DisableForwarding|^DisableForwarding" + line: 'DisableForwarding yes' + + - name: "4.2.8 | PATCH | Ensure sshd DisableForwarding is enabled | ensure x11 disabled" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: ^X11Forwarding (yes|no) + line: '#DisableForwarding yes' + +- name: "4.2.9 | PATCH | Ensure SSH HostbasedAuthentication is disabled" + when: + - rhel8cis_rule_4_2_9 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.9 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: ^#HostbasedAuthentication|^HostbasedAuthentication" + line: 'HostbasedAuthentication no' + +- name: "4.2.10 | PATCH | Ensure SSH IgnoreRhosts is enabled" + when: + - rhel8cis_rule_4_2_10 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.10 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#IgnoreRhosts|^IgnoreRhosts" + line: 'IgnoreRhosts yes' + +- name: "4.2.11 | PATCH | Ensure sshd KexAlgorithms is configured" + when: + - rhel8cis_rule_4_2_11 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - kex + - NIST800-53R5_SC-8 + - rule_4.2.11 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#KexAlgorithms|^KexAlgorithms" + line: "KexAlgorithms {{ rhel8cis_sshd['kex'] }}" + +- name: "4.2.12 | PATCH | Ensure sshd LoginGraceTime is configured" + when: + - rhel8cis_rule_4_2_12 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-6 + - rule_4.2.12 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#LoginGraceTime|^LoginGraceTime" + line: "LoginGraceTime {{ rhel8cis_sshd['logingracetime'] }}" + +- name: "4.2.13 | PATCH | Ensure sshd LogLevel is configured" + when: + - rhel8cis_rule_4_2_13 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - rule_4.2.13 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#LogLevel|^LogLevel" + line: "LogLevel {{ rhel8cis_sshd['loglevel'] }}" + +- name: "4.2.14 | PATCH | Ensure sshd MACs are configured" + when: + - rhel8cis_rule_4_2_14 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - macs + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.14 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#MACs|^MACs" + line: "MACs {{ rhel8cis_sshd['macs'] }}" + +- name: "4.2.15 | PATCH | Ensure sshd MaxAuthTries is configured" + when: + - rhel8cis_rule_4_2_15 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_AU-3 + - rule_4.2.15 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: '^(#)?MaxAuthTries \d' + line: "MaxAuthTries {{ rhel8cis_sshd['maxauthtries'] }}" + +- name: "4.2.16 | PATCH | Ensure sshd MaxSessions is configured" + when: + - rhel8cis_rule_4_2_16 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.16 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#MaxSessions|^MaxSessions" + line: "MaxSessions {{ rhel8cis_sshd['maxsessions'] }}" + +- name: "4.2.17 | PATCH | Ensure sshd MaxStartups is configured" + when: + - rhel8cis_rule_4_2_17 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.17 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: (?i)MaxStartups + line: "MaxStartups {{ rhel8cis_sshd['maxstartups'] }}" + +- name: "4.2.18 | PATCH | Ensure SSH PermitEmptyPasswords is disabled" + when: + - rhel8cis_rule_4_2_18 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.18 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#PermitEmptyPasswords|^PermitEmptyPasswords" + line: 'PermitEmptyPasswords no' + +- name: "4.2.19 | PATCH | Ensure sshd PermitRootLogin is disabled" + when: + - rhel8cis_rule_4_2_19 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_AC-6 + - rule_4.2.19 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#PermitRootLogin|^PermitRootLogin" + line: 'PermitRootLogin no' + +- name: "4.2.20 | PATCH | Ensure sshd PermitUserEnvironment is disabled" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#PermitUserEnvironment|^PermitUserEnvironment" + line: 'PermitUserEnvironment no' + when: + - rhel8cis_rule_4_2_20 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.20 + +- name: "4.2.21 | PATCH | Ensure sshd UsePAM is enabled" + when: + - rhel8cis_rule_4_2_21 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.21 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#UsePAM|^UsePAM" + line: 'UsePAM yes' + +- name: "4.2.22 | PATCH | Ensure sshd crypto_policy is not set" + when: + - rhel8cis_rule_4_2_22 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_SC-8 + - NIST800-53R5_IA-5 + - NIST800-53R5_AC-17 + - rule_4.2.22 + block: + - name: "4.2.22 | AUDIT | Ensure system-wide crypto policy is not over-ridden" + ansible.builtin.shell: grep -i '^\s*CRYPTO_POLICY=' /etc/sysconfig/sshd + failed_when: ( crypto_policy_override.rc not in [ 0, 1 ] ) + changed_when: false + register: crypto_policy_override + + - name: "4.2.22 | PATCH | Ensure system-wide crypto policy is not over-ridden" + ansible.builtin.shell: sed -ri "s/^\s*(CRYPTO_POLICY\s*=.*)$/# \1/" /etc/sysconfig/sshd + notify: Restart_sshd + when: + - crypto_policy_override.stdout | length > 0 diff --git a/tasks/section_4/cis_4.3.x.yml b/tasks/section_4/cis_4.3.x.yml new file mode 100644 index 00000000..2978b308 --- /dev/null +++ b/tasks/section_4/cis_4.3.x.yml @@ -0,0 +1,151 @@ +--- + +- name: "4.3.1 | PATCH | Ensure sudo is installed" + when: + - rhel8cis_rule_4_3_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-6 + - sudo + - rule_4.3.1 + ansible.builtin.package: + name: sudo + state: present + +- name: "4.3.2 | PATCH | Ensure sudo commands use pty" + when: + - rhel8cis_rule_4_3_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-6 + - sudo + - rule_4.3.2 + ansible.builtin.lineinfile: + path: /etc/sudoers + line: "Defaults use_pty" + validate: '/usr/sbin/visudo -cf %s' + +- name: "4.3.3 | PATCH | Ensure sudo log file exists" + when: + - rhel8cis_rule_4_3_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + - sudo + - rule_4.3.3 + ansible.builtin.lineinfile: + path: /etc/sudoers + regexp: '^Defaults\s+logfile=' + line: 'Defaults logfile={{ rhel8cis_sudolog_location }}' + +- name: "4.3.4 | PATCH | Ensure users must provide password for escalation" + when: + - rhel8cis_rule_4_3_4 + tags: + - level2-server + - level2-workstation + - automated + - patch + - NIST800-53R5_AC-6 + - sudo + - rule_4.3.4 + ansible.builtin.replace: + path: "{{ item }}" + regexp: '^([^#|{% if system_is_ec2 %}ec2-user{% endif %}].*)NOPASSWD(.*)' + replace: '\1PASSWD\2' + validate: '/usr/sbin/visudo -cf %s' + loop: "{{ rhel8cis_sudoers_files.stdout_lines }}" + +- name: "4.3.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally" + when: + - rhel8cis_rule_4_3_5 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-6 + - sudo + - rule_4.3.5 + ansible.builtin.replace: + path: "{{ item }}" + regexp: '^([^#].*)!authenticate(.*)' + replace: '\1authenticate\2' + validate: '/usr/sbin/visudo -cf %s' + loop: "{{ rhel8cis_sudoers_files.stdout_lines }}" + +- name: "4.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly" + when: + - rhel8cis_rule_4_3_6 + tags: + - level1-server + - level1-workstation + - automated + - patch + - sudo + - rule_4.3.6 + block: + - name: "4.3.6 | AUDIT | Ensure sudo authentication timeout is configured correctly | Get files with timeout set" + ansible.builtin.shell: grep -is 'timestamp_timeout' /etc/sudoers /etc/sudoers.d/* | cut -d":" -f1 | uniq | sort + changed_when: false + failed_when: false + register: rhel8cis_4_3_6_timeout_files + + - name: "4.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if no results" + when: rhel8cis_4_3_6_timeout_files.stdout | length == 0 + ansible.builtin.lineinfile: + path: /etc/sudoers + regexp: 'Defaults timestamp_timeout=' + line: "Defaults timestamp_timeout={{ rhel8cis_sudo_timestamp_timeout }}" + validate: '/usr/sbin/visudo -cf %s' + + - name: "4.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if has results" + when: rhel8cis_4_3_6_timeout_files.stdout | length > 0 + ansible.builtin.replace: + path: "{{ item }}" + regexp: 'timestamp_timeout=(\d+)' + replace: "timestamp_timeout={{ rhel8cis_sudo_timestamp_timeout }}" + validate: '/usr/sbin/visudo -cf %s' + loop: "{{ rhel8cis_4_3_6_timeout_files.stdout_lines }}" + +- name: "4.3.7 | PATCH | Ensure access to the su command is restricted" + when: + - rhel8cis_rule_4_3_7 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - sudo + - rule_4.3.7 + block: + - name: "4.3.7 | PATCH | Ensure access to the su command is restricted | Ensure sugroup exists" + ansible.builtin.group: + name: "{{ rhel8cis_sugroup }}" + state: present + register: rhel8cis_4_3_7_sugroup + + - name: "4.3.7 | PATCH | Ensure access to the su command is restricted | remove users from group" + ansible.builtin.lineinfile: + path: /etc/group + regexp: '^{{ rhel8cis_sugroup }}(:.:.*:).*$' + line: '{{ rhel8cis_sugroup }}\g<1>' + backrefs: true + + - name: "4.3.7 | PATCH | Ensure access to the su command is restricted | Setting pam_wheel to use_uid" + ansible.builtin.lineinfile: + path: /etc/pam.d/su + regexp: '^(#)?auth\s+required\s+pam_wheel\.so' + line: 'auth required pam_wheel.so use_uid group={{ rhel8cis_sugroup }}' diff --git a/tasks/section_4/cis_4.3.yml b/tasks/section_4/cis_4.3.yml deleted file mode 100644 index 0797b80c..00000000 --- a/tasks/section_4/cis_4.3.yml +++ /dev/null @@ -1,28 +0,0 @@ ---- - -- name: "4.3 | PATCH | Ensure logrotate is configured" - block: - - name: "4.3 | AUDIT | Ensure logrotate is configured | Get logrotate settings" - ansible.builtin.find: - paths: /etc/logrotate.d/ - register: log_rotates - - - name: "4.3 | PATCH | Ensure logrotate is configured" - ansible.builtin.replace: - path: "{{ item.path }}" - regexp: '^(\s*)(daily|weekly|monthly|yearly)$' - replace: "\\1{{ rhel8cis_logrotate }}" - with_items: - - "{{ log_rotates.files }}" - - { path: "/etc/logrotate.conf" } - loop_control: - label: "{{ item.path }}" - when: - - rhel8cis_rule_4_3 - tags: - - level1-server - - level1-workstation - - manual - - patch - - logrotate - - rule_4.3 diff --git a/tasks/section_4/cis_4.4.1.x.yml b/tasks/section_4/cis_4.4.1.x.yml new file mode 100644 index 00000000..e5db2ce4 --- /dev/null +++ b/tasks/section_4/cis_4.4.1.x.yml @@ -0,0 +1,37 @@ +--- + +- name: "4.4.1.1 | PATCH | Ensure latest version of pam is installed" + when: + - rhel8cis_rule_4_4_1_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_4.4.1.1 + ansible.builtin.package: + name: pam + state: latest + +- name: "4.4.1.2 | PATCH | Ensure latest version of authselect is installed" + when: + - rhel8cis_rule_4_4_1_2 + - rhel8cis_authselect_pkg_update + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_4.4.1.2 + ansible.builtin.package: + name: authselect + state: latest + +- name: "4.4.1.1 and 4.4.1.2 | Update package facts" + when: + - rhel8cis_rule_4_4_1_1 or + rhel8cis_rule_4_4_1_2 + ansible.builtin.package_facts: + manager: auto diff --git a/tasks/section_4/cis_4.4.2.x.yml b/tasks/section_4/cis_4.4.2.x.yml new file mode 100644 index 00000000..8fe19004 --- /dev/null +++ b/tasks/section_4/cis_4.4.2.x.yml @@ -0,0 +1,168 @@ +--- + +- name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used" + when: + - rhel8cis_rule_4_4_2_1 + - authselect_version == "OK" + - pam_version == "OK" + - rhel8cis_disruption_high + tags: + - level1-server + - level1-workstation + - manual + - patch + - authselect + - rule_4.4.2.1 + block: + - name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used | Create custom profiles" + when: + - "rhel8cis_authselect['custom_profile_name'] not in authselect_running_config.stdout" + - rhel8cis_authselect_custom_profile_create + - not rhel8cis_4_4_2_1_profile.stat.exists + ansible.builtin.shell: "/usr/bin/authselect create-profile {{ rhel8cis_authselect['custom_profile_name'] }} -b {{ rhel8cis_authselect['default_file_to_copy'] }}" + args: + creates: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}" + + - name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used | Select profiles" + when: + - "rhel8cis_authselect['custom_profile_name'] not in authselect_running_config.stdout" + - rhel8cis_authselect_custom_profile_select + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel8cis_authselect['custom_profile_name'] }}{% if rhel8cis_rule_4_4_2_2 %} with-faillock{% endif %}{% if rhel8cis_rule_4_4_2_4 %} with-pwhistory{% endif %}{% if rhel8cis_rule_4_4_3_4_1 %} without-nullok{% endif %} --force" + +- name: "4.4.2.2 | PATCH | Ensure pam_faillock module is enabled" + when: + - rhel8cis_rule_4_4_2_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - authselect + - rule_4.4.2.2 + notify: Update_authselect + block: + - name: "4.4.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config" + ansible.builtin.shell: authselect current | grep faillock + changed_when: false + failed_when: rhel8cis_authselect_current.rc not in [ 0, 1 ] + register: rhel8cis_authselect_current + + - name: "4.4.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" + when: rhel8cis_authselect_current.rc != 0 + ansible.builtin.shell: "authselect enable-feature with-faillock" + +- name: "4.4.2.3 | PATCH | Ensure pam_pwquality module is enabled" + when: + - rhel8cis_rule_4_4_2_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - authselect + - rule_4.4.2.3 + notify: Update_authselect + block: + - name: "4.4.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Capture current state" + ansible.builtin.shell: | + grep -P -- '\bpam_pwquality\.so\b' /etc/pam.d/{password,system}-auth + changed_when: false + failed_when: rhel8cis_pwquality_enabled.rc not in [ 0, 1 ] + register: rhel8cis_pwquality_enabled + + - name: "4.4.2.3 | PATCH | Ensure pam_pwquality module is enabled | system-auth" + when: "'system-auth:password' not in rhel8cis_pwquality_enabled.stdout" + ansible.builtin.lineinfile: + backrefs: true + insertbefore: "{{ item.before | default (omit) }}" + line: "{{ item.line }}" + path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/system-auth + regexp: "{{ item.regexp }}" + loop: + - { regexp: '^(password\s+)(required|requisite|sufficient)(\s+pam_pwquality.so.*)(.*)', line: '\1requisite\3\4', before: '^password\s+[default=1 ignore=ignore success=ok]' } + + - name: "4.4.2.3 | PATCH | Ensure pam_pwquality module is enabled | password-auth" + when: "'password-auth:password' not in rhel8cis_pwquality_enabled.stdout" + ansible.builtin.lineinfile: + backrefs: true + insertafter: "{{ item.after | default (omit) }}" + insertbefore: "{{ item.before | default (omit) }}" + line: "{{ item.line }}" + path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/password-auth + regexp: "{{ item.regexp }}" + loop: + - { regexp: '^(password\s+)(required|requisite|sufficient)(\s+pam_pwquality.so.*)(.*)', line: '\1requisite\3\4', before: '^password\s+[default=1 ignore=ignore success=ok]' } + +- name: "4.4.2.4 | PATCH | Ensure pam_pwhistory module is enabled" + when: + - rhel8cis_rule_4_4_2_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - authselect + - rule_4.4.2.4 + notify: Update_authselect + block: + - name: "4.4.2.4 | AUDIT | Ensure pam_pwhistory module is enabled | Get current config" + ansible.builtin.shell: authselect current | grep pwhistory + changed_when: false + failed_when: rhel8cis_authselect_current.rc not in [ 0, 1 ] + register: rhel8cis_authselect_current + + - name: "4.4.2.4 | PATCH | Ensure pam_pwhistory module is enabled | enable feature" + when: rhel8cis_authselect_current.rc != 0 + ansible.builtin.shell: "authselect enable-feature with-pwhistory" + +- name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled" + when: + - rhel8cis_rule_4_4_2_5 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - authselect + - rule_4.4.2.5 + block: + - name: "4.4.2.5 | AUDIT | Ensure pam_unix module is enabled" + ansible.builtin.shell: | + grep -P -- '\b(pam_unix\.so)\b' /etc/authselect/"$(head -1 /etc/authselect/authselect.conf)"/{system,password}-auth + changed_when: false + failed_when: rhel8cis_authselect_pam_unix.rc not in [ 0, 1 ] + register: rhel8cis_authselect_pam_unix + + - name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled | system-auth" + when: "'system-auth:password' not in rhel8cis_authselect_pam_unix.stdout" + ansible.builtin.lineinfile: + backrefs: true + insertafter: "{{ item.after | default (omit) }}" + insertbefore: "{{ item.before | default (omit) }}" + line: "{{ item.line }}" + path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/system-auth + regexp: "{{ item.regexp }}" + loop: + - { regexp: '^(auth\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', after: '^auth.*pam_faillock.*preauth' } + - { regexp: '^(password\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', before: '^password.*pam_deny.so' } + + - name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled | password-auth" + when: "'password-auth:password' not in rhel8cis_authselect_pam_unix.stdout" + ansible.builtin.lineinfile: + backrefs: true + insertafter: "{{ item.after | default (omit) }}" + insertbefore: "{{ item.before | default (omit) }}" + line: "{{ item.line }}" + path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/password-auth + regexp: "{{ item.regexp }}" + loop: + - { regexp: '^(auth\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\2', after: '^auth.*pam_faillock.*preauth' } + - { regexp: '^(password\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', before: '^password.*pam_deny.so' } diff --git a/tasks/section_4/cis_4.4.3.1.x.yml b/tasks/section_4/cis_4.4.3.1.x.yml new file mode 100644 index 00000000..dd45f4b9 --- /dev/null +++ b/tasks/section_4/cis_4.4.3.1.x.yml @@ -0,0 +1,131 @@ +--- + +- name: "4.4.3.1.1 | PATCH | Ensure password failed attempts lockout is configured" + when: + - rhel8cis_rule_4_4_3_1_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_4.4.3.1.1 + block: + - name: "4.4.3.1.1 | PATCH | Ensure password failed attempts lockout is configured | faillock.conf" + ansible.builtin.lineinfile: + path: /etc/security/faillock.conf + state: present + regexp: '^(#|)\s*deny\s*=\s*\d' + line: "deny = {{ rhel8cis_pam_faillock['deny'] }}" + + - name: "4.4.3.1.1 | PATCH | Ensure password failed attempts lockout is configured | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+deny\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.2.2 | AUDIT | Ensure pam_faillock module is enabled | get current state" + when: + - rhel8cis_allow_authselect_updates + ansible.builtin.shell: authselect current + changed_when: false + failed_when: rhel8cis_authselect_current.rc not in [ 0, 1 ] + register: rhel8cis_authselect_current + + - name: "4.4.3.1.1 | PATCH | Ensure password failed attempts lockout is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - rhel8cis_authselect_current.rc != 0 + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+deny\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.1.2 | PATCH | Ensure password unlock time is configured" + when: + - rhel8cis_rule_4_4_3_1_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_4.4.3.1.2 + block: + - name: "4.4.3.1.2 | PATCH | Ensure password unlock time is configured | faillock.conf" + ansible.builtin.lineinfile: + path: /etc/security/faillock.conf + state: present + regexp: '^(#|)\s*unlock_time\s*=\s*\d' + line: "unlock_time = {{ rhel8cis_pam_faillock['unlock_time'] }}" + + - name: "4.4.3.1.2 | PATCH | Ensure password unlock time is configured | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+unlock_time\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.1.2 | PATCH | Ensure password unlock time is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+unlock_time\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account" + when: + - rhel8cis_rule_4_4_3_1_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_4.4.3.1.3 + block: + - name: "4.4.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | faillock.conf" + ansible.builtin.lineinfile: + path: /etc/security/faillock.conf + state: present + regexp: ^(#|)\s*"{{ rhel8cis_pam_faillock['root_option'] }}"(\s*=\s*\d|.*) + line: "{{ rhel8cis_pam_faillock['root_option'] }}" + + - name: "4.4.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s"{{ rhel8cis_pam_faillock['root_option'] }}"(\s*=\s*\d|.*)\S+(.*$) + replace: \1\2\3\4 + loop: + - password + - system + + - name: "4.4.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s"{{ rhel8cis_pam_faillock['root_option'] }}"(\s*=\s*\d|.*)\S+(.*$) + replace: \1\2\3\4 + loop: + - password + - system diff --git a/tasks/section_4/cis_4.4.3.2.x.yml b/tasks/section_4/cis_4.4.3.2.x.yml new file mode 100644 index 00000000..356b5935 --- /dev/null +++ b/tasks/section_4/cis_4.4.3.2.x.yml @@ -0,0 +1,294 @@ +--- + +- name: "4.4.3.2.1 | PATCH | Ensure password number of changed characters is configured" + when: + - rhel8cis_rule_4_4_3_2_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.2.1 + block: + - name: "4.4.3.2.1 | PATCH | Ensure password number of changed characters is configured | pwquality.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwquality.conf + state: present + regexp: '^(#|)\s*difok\s*=\s*\d' + line: "difok = {{ rhel8cis_pam_pwquality['difok'] }}" + + - name: "4.4.3.2.1 | PATCH | Ensure password number of changed characters is configured | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+difok\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.2.1 | PATCH | Ensure password number of changed characters is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+difok\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.2.2 | PATCH | Ensure password length is configured" + when: + - rhel8cis_rule_4_4_3_2_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.2.2 + block: + - name: "4.4.3.2.2 | PATCH | Ensure password length is configured | pwquality.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwquality.conf + state: present + regexp: '^(#|)\s*minlen\s*=\s*\d' + line: "minlen = {{ rhel8cis_pam_pwquality['minlen'] }}" + + - name: "4.4.3.2.2 | PATCH | Ensure password length is configured | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+minlen\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.2.2 | PATCH | Ensure password length is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+minlen\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.2.3 | PATCH | Ensure password complexity is configured" + when: + - rhel8cis_rule_4_4_3_2_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.2.3 + block: + - name: "4.4.3.2.3 | PATCH | Ensure password complexity is configured | pwquality.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwquality.conf + state: present + regexp: '^(#|)\s*minclass\s*=\s*\d' + line: "minclass = {{ rhel8cis_pam_pwquality['minclass'] }}" + + - name: "4.4.3.2.3 | PATCH | Ensure password complexity is configured | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+minclass\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.2.3 | PATCH | Ensure password complexity is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+minclass\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.2.4 | PATCH | Ensure password same consecutive characters is configured" + when: + - rhel8cis_rule_4_4_3_2_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.2.4 + block: + - name: "4.4.3.2.4 | PATCH | Ensure password same consecutive characters is configured | pwquality.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwquality.conf + state: present + regexp: '^(#|)\s*maxrepeat\s*=\s*\d' + line: "maxrepeat = {{ rhel8cis_pam_pwquality['maxrepeat'] }}" + + - name: "4.4.3.2.4 | PATCH | Ensure password same consecutive characters is configured | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxrepeat\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.2.4 | PATCH | Ensure password same consecutive characters is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxrepeat\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.2.5 | PATCH | Ensure password maximum sequential characters is configured" + when: + - rhel8cis_rule_4_4_3_2_5 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.2.5 + block: + - name: "4.4.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | pwquality.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwquality.conf + state: present + regexp: '^(#|)\s*maxseq\s*=\s*\d' + line: "maxseq = {{ rhel8cis_pam_pwquality['maxseq'] }}" + + - name: "4.4.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxseq\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.2.5 | PATCH | Ensure password same consecutive characters is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxseq\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.2.6 | PATCH | Ensure password dictionary check is enabled" + when: + - rhel8cis_rule_4_4_3_2_6 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.2.6 + block: + - name: "4.4.3.2.6 | PATCH | Ensure password dictionary check is enabled | pwquality.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwquality.conf + state: absent + regexp: '^(#|)\s*dictcheck\s*=\s*\d' + + - name: "4.4.3.2.6 | PATCH | Ensure password dictionary check is enabled | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+dictcheck\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.2.6 | PATCH | Ensure password dictionary check is enabled | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+dictcheck\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.2.7 | PATCH | Ensure password quality is enforced for the root user" + when: + - rhel8cis_rule_4_4_3_2_7 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.2.7 + block: + - name: "4.4.3.2.7 | PATCH | Ensure password quality is enforced for the root user | pwquality.conf" + ansible.builtin.lineinfile: + line: enforce_for_root + path: /etc/security/pwquality.conf + state: present + regexp: '^(#|)\s*enforce_for_root' + + - name: "4.4.3.2.7 | PATCH | Ensure password dictionary check is enabled | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+enforce_for_root(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.2.7 | PATCH | Ensure password dictionary check is enabled | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+enforce_for_root(.*$) + replace: \1\2\3 + loop: + - password + - system diff --git a/tasks/section_4/cis_4.4.3.3.x.yml b/tasks/section_4/cis_4.4.3.3.x.yml new file mode 100644 index 00000000..b6957406 --- /dev/null +++ b/tasks/section_4/cis_4.4.3.3.x.yml @@ -0,0 +1,118 @@ +--- + +- name: "4.4.3.3.1 | PATCH | Ensure password history remember is configured" + when: + - rhel8cis_rule_4_4_3_3_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.3.1 + block: + - name: "4.4.3.3.1 | PATCH | Ensure password history remember is configured | pwhistory.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwhistory.conf + state: present + regexp: '^(#|)\s*remember\s*=\s*\d' + line: "remember = {{ rhel8cis_pam_pwhistory['remember'] }}" + + - name: "4.4.3.3.1 | PATCH | Ensure password number of changed characters is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\s+remember\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.3.2 | PATCH | Ensure password history is enforced for the root user" + when: + - rhel8cis_rule_4_4_3_3_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.3.2 + block: + - name: "4.4.3.3.2 | PATCH | Ensure password history is enforced for the root user | pwhistory.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwhistory.conf + state: present + regexp: '^(#|)\s*enforce_for_root' + line: "enforce_for_root" + + - name: "4.4.3.3.2 | PATCH | Ensure password history is enforced for the root user | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\s+enforce_for_root(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.3.2 | PATCH | Ensure password history is enforced for the root user | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\s+enforce_for_root(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok" + when: + - rhel8cis_rule_4_4_3_3_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.3.3 + block: + - name: "4.4.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | pwhistory.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwhistory.conf + state: present + regexp: '^(#|)\s*use_authtok' + line: "use_authtok" + + - name: "4.4.3.3.3 | AUDIT | Ensure pam_pwhistory includes use_authtok | Get current state" + ansible.builtin.shell: | + grep -P -- '^\h*password\h+([^#\n\r]+)\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?use_authtok\ b' /etc/pam.d/{password,system}-auth + changed_when: false + failed_when: rhel8cis_pwhistory_authtok.rc not in [ 0, 1 ] + register: rhel8cis_pwhistory_authtok + + - name: "4.4.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - rhel8cis_pwhistory_authtok.rc != 0 + notify: Update_authselect + community.general.pamd: + name: "{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}" + type: password + control: requisite + module_path: pam_pwhistory.so + module_arguments: 'use_authtok' + state: updated + loop: + - password + - system diff --git a/tasks/section_4/cis_4.4.3.4.x.yml b/tasks/section_4/cis_4.4.3.4.x.yml new file mode 100644 index 00000000..e6b8a128 --- /dev/null +++ b/tasks/section_4/cis_4.4.3.4.x.yml @@ -0,0 +1,174 @@ +--- + +- name: "4.4.3.4.1 | PATCH | Ensure pam_unix does not include nullok" + when: + - rhel8cis_rule_4_4_3_4_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_4.4.3.4.1 + block: + - name: "4.4.3.4.1 | PATCH | Ensure pam_unix does not include nullok | capture state" + ansible.builtin.shell: grep -P -- '^\h*(auth|account|password|session)\h+(requisite|required|sufficient)\h+pam_unix\.so\b' /etc/pam.d/{password,system}-auth | grep -P -- '\bnullok\b' + changed_when: false + failed_when: rhel8cis_pam_nullok.rc not in [ 0, 1 ] + register: rhel8cis_pam_nullok + + - name: "4.4.3.4.1 | PATCH | Ensure pam_unix does not include nullok | pam_files" + when: + - rhel8cis_pam_nullok.stdout | length > 0 + - not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)nullok(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.4.1 | PATCH | Ensure pam_unix does not include nullok | update authselect" + when: + - rhel8cis_pam_nullok is defined + - rhel8cis_pam_nullok.stdout | length > 0 + - rhel8cis_allow_authselect_updates + notify: Update_authselect + ansible.builtin.shell: authselect enable-feature without-nullok + +- name: "4.4.3.4.2 | PATCH | Ensure pam_unix does not include remember" + when: + - rhel8cis_rule_4_4_3_4_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.4.2 + block: + - name: "4.4.3.4.2 | AUDIT | Ensure pam_unix does not include remember | capture state" + ansible.builtin.shell: grep -Pi '^\h*password\h+([^#\n\r]+\h+)?pam_unix\.so\b' /etc/pam.d/{password,system}-auth | grep -P '\bremember=\d\b' + changed_when: false + failed_when: rhel8cis_pam_remember.rc not in [ 0, 1 ] + register: rhel8cis_pam_remember + + - name: "4.4.3.4.2 | PATCH | Ensure pam_unix does not include remember | pam_files" + when: + - rhel8cis_pam_remember is defined + - rhel8cis_pam_remember | length > 0 + - not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)remember\s*=\s*\d+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.4.2 | PATCH | Ensure pam_unix does not include remember | authconfig_files" + when: + - rhel8cis_pam_remember is defined + - rhel8cis_pam_remember | length > 0 + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)remember\s*=\s*\d+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm" + when: + - rhel8cis_rule_4_4_3_4_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.4.3 + block: + - name: "4.4.3.4.3 | AUDIT | Ensure pam_unix includes a strong password hashing algorithm | capture state" + ansible.builtin.shell: grep -P -- '^\h*password\h+([^#\n\r]+)\h+pam_unix\.so\h+([^#\n\r]+\h+)?(sha512|yescrypt)\b' /etc/pam.d/{password,system}-auth | grep -v {{ rhel8cis_pam_pwhash }} + changed_when: false + failed_when: rhel8cis_pam_pwhash.rc not in [ 0, 1 ] + register: rhel8cis_pam_pwhash + + - name: "4.4.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | pam_files" + when: + - rhel8cis_pam_pwhash is defined + - rhel8cis_pam_pwhash | length > 0 + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)(sha512|yescrypt)\s*=\s*\d+(.*$) + replace: \1\2\4 {{ rhel8cis_pam_pwhash }} + loop: + - password + - system + + - name: "4.4.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | authselect_files" + when: + - rhel8cis_pam_pwhash is defined + - rhel8cis_pam_pwhash | length > 0 + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)(sha512|yescrypt)\s*=\s*\d+(.*$) + replace: \1\2\4 {{ rhel8cis_pam_pwhash }} + loop: + - password + - system + +- name: "4.4.3.4.4 | PATCH | Ensure pam_unix includes use_authtok" + when: + - rhel8cis_rule_4_4_3_4_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.4.4 + block: + - name: "4.4.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | capture state" + ansible.builtin.shell: grep -P -- '^\h*password\h+([^#\n\r]+)\h+pam_unix\.so\h+([^#\n\r]+\h+)?use_authtok\b' /etc/pam.d/{password,system}-auth | grep -v use_authtok + changed_when: false + failed_when: rhel8cis_pam_authtok.rc not in [ 0, 1 ] + register: rhel8cis_pam_authtok + + - name: "4.4.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | pam_files" + when: + - rhel8cis_pam_authtok is defined + - rhel8cis_pam_authtok | length > 0 + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\s+use_authtok\s*=\s*\S+(.*$) + replace: \1\2\3 use_authtok + loop: + - password + - system + + - name: "4.4.3.4.4 | PATCH | Ensure password same consecutive characters is configured | authselect_files" + when: + - rhel8cis_pam_authtok is defined + - rhel8cis_pam_authtok | length > 0 + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\s+use_authtok\s*=\s*\S+(.*$) + replace: \1\2\3 use_authtok + loop: + - password + - system diff --git a/tasks/section_4/cis_4.5.1.x.yml b/tasks/section_4/cis_4.5.1.x.yml new file mode 100644 index 00000000..a1910fb4 --- /dev/null +++ b/tasks/section_4/cis_4.5.1.x.yml @@ -0,0 +1,196 @@ +--- + +- name: "4.5.1.1 | PATCH | Ensure strong password hashing algorithm is configured" + when: + - rhel8cis_rule_4_5_1_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - shadow_suite + - rule_4.5.1.1 + ansible.builtin.lineinfile: + path: /etc/libuser.conf + regexp: ^(#|)\s*crypt_style\s*=\s* + line: "crypt_style = {{ rhel8cis_pam_pwhash }}" + +- name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less" + when: + - rhel8cis_rule_4_5_1_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - shadow_suite + - rule_4.5.1.2 + block: + - name: "4.5.1.2 | AUDIT | Ensure password expiration is 365 days or less | Capture accounts more than 365" + ansible.builtin.shell: "grep -E '^[^:]+:[^!*]' /etc/shadow | awk -F':' '$5>{{ rhel8cis_pass['max_days'] }} { print $1 }'" + changed_when: false + failed_when: rhel8cis_4_5_1_2_pass_max_expire.rc not in [ 0, 1 ] + register: rhel8cis_4_5_1_2_pass_max_expire + + - name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less | update login.defs" + ansible.builtin.lineinfile: + path: /etc/login.defs + regexp: '^PASS_MAX_DAYS' + line: "PASS_MAX_DAYS {{ rhel8cis_pass['max_days'] }}" + + - name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less | Ensure all accounts set to 365" + ansible.builtin.user: + name: "{{ item }}" + password_expire_max: "{{ rhel8cis_pass['max_days'] }}" + loop: "{{ rhel8cis_4_5_1_2_pass_max_expire.stdout_lines | default([]) }}" + when: + - rhel8cis_4_5_1_2_set_max_expiry + - item not in rhel8cis_4_5_1_2_user_skip_list + + - name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less | Warning" + block: + - name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less | Output list if not set to change" + ansible.builtin.debug: + msg: | + "Warning!! The following account are set beyond the expected expiration date: + {{ rhel8cis_4_5_1_2_pass_max_expire.stdout_lines | default([]) }}" + + - name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less | set warning fact" + ansible.builtin.import_tasks: warning_facts.yml + vars: + warn_control_id: '4.5.1.2' + when: + - rhel8cis_4_5_1_2_pass_max_expire is defined + - rhel8cis_4_5_1_2_pass_max_expire.stdout | length > 0 + - not rhel8cis_4_5_1_2_set_max_expiry + +- name: "4.5.1.3 | PATCH | Ensure password expiration warning days is 7 or more" + when: + - rhel8cis_rule_4_5_1_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - shadow_suite + - rule_4.5.1.3 + block: + - name: "4.5.1.3 | PATCH | Ensure password expiration warning days is 7 or more | set login.defs" + ansible.builtin.lineinfile: + path: /etc/login.defs + regexp: ^(#|)\s*PASS_WARN_AGE\s+\d+ + line: "PASS_WARN_AGE {{ rhel8cis_pass['warn_age'] }}" + + - name: "4.5.1.3 | AUDIT | Ensure password expiration warning days is 7 or more | capture users not matching" + ansible.builtin.shell: | + awk -F: '/^[^:\n\r]+:[^!*xX\n\r]/ {print $1}' /etc/shadow + changed_when: false + failed_when: rhel8cis_users_warn_days.rc not in [ 0, 1 ] + register: rhel8cis_users_warn_days + + - name: "4.5.1.3 | PATCH | Ensure password expiration warning days is 7 or more | change users not matching req" + when: + - rhel8cis_users_warn_days is defined + - rhel8cis_users_warn_days.stdout | length > 0 + ansible.builtin.shell: chage --warndays {{ rhel8cis_pass['warn_age'] }} {{ item }} + loop: "{{ rhel8cis_users_warn_days.stdout_lines }}" + +- name: "4.5.1.4 | PATCH | Ensure inactive password lock is 30 days or less" + when: + - rhel8cis_rule_4_5_1_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - shadow_suite + - rule_4.5.1.4 + block: + - name: "4.5.1.4 | AUDIT | Ensure inactive password lock is 30 days or less | capture default state" + ansible.builtin.shell: useradd -D | grep INACTIVE + changed_when: false + failed_when: rhel8cis_users_inactive_def.rc not in [ 0, 1 ] + register: rhel8cis_users_inactive_def + + - name: "4.5.1.4 | PATCH | Ensure inactive password lock is 30 days or less | change default" + when: + - rhel8cis_users_inactive_def is defined + - "'30' not in rhel8cis_users_inactive_def.stdout" + ansible.builtin.shell: useradd -D -f {{ rhel8cis_pass['inactive'] }} + + - name: "4.5.1.4 | AUDIT | Ensure inactive password lock is 30 days or less | capture users not matching" + ansible.builtin.shell: | + awk -F: '/^[^#:]+:[^!*:]*:[^:]*:[^:]*:[^:]*:[^:]*:(\s*|-1|3[1-9]|[4-9][0-9]|[1-9][0-9][0-9]+):[^:]*:[^:]*\s*$/ {print $1}' /etc/shadow + changed_when: false + failed_when: rhel8cis_users_inactive.rc not in [ 0, 1 ] + register: rhel8cis_users_inactive + + - name: "4.5.1.4 | PATCH | Ensure inactive password lock is 30 days or less | change users not matching req" + when: + - rhel8cis_users_inactive is defined + - rhel8cis_users_inactive.stdout | length > 0 + ansible.builtin.shell: chage --inactive {{ rhel8cis_pass['inactive'] }} {{ item }} + loop: "{{ rhel8cis_users_inactive.stdout_lines }}" + +- name: "4.5.1.5 | PATCH | Ensure all users last password change date is in the past" + when: + - rhel8cis_rule_4_5_1_5 + tags: + - level1-server + - level1-workstation + - automated + - patch + - shadow_suite + - rule_4.5.1.5 + vars: + warn_control_id: '4.5.1.5' + block: + - name: "4.5.1.5 | AUDIT | Ensure all users last password change date is in the past | capture default state" + ansible.builtin.shell: useradd -D | grep INACTIVE + changed_when: false + failed_when: rhel8cis_users_inactive_def.rc not in [ 0, 1 ] + register: rhel8cis_users_inactive_def + + - name: "4.5.1.5 | PATCH | Ensure all users last password change date is in the past | change default" + when: + - rhel8cis_users_inactive_def is defined + - "'30' not in rhel8cis_users_inactive_def.stdout" + ansible.builtin.shell: useradd -D -f {{ rhel8cis_pass['inactive'] }} + + - name: "4.5.1.5 | FACT | Ensure inactive password lock is 30 days or less | set fact days since_epoch" + ansible.builtin.set_fact: + days_since_epoch: "{{ (ansible_facts['date_time']['epoch']|int)/86400 }}" + + - name: "4.5.1.5 | AUDIT | Ensure inactive password lock is 30 days or less | capture users date in future" + ansible.builtin.shell: | + awk -F: '{ if ($3 > "{{ days_since_epoch }}") { print $1 } }' /etc/shadow + changed_when: false + failed_when: rhel8cis_users_user_future.rc not in [ 0, 1 ] + register: rhel8cis_users_user_future + + - name: "4.5.1.5 | WARN | Ensure inactive password lock is 30 days or less | Warn Users in future" + when: + - rhel8cis_users_user_future + - rhel8cis_users_user_future.stdout | length > 0 + ansible.builtin.debug: + msg: + - "Warning!! - The following users have passwords set in the future please investigate" + - "{{ rhel8cis_users_user_future.stdout_lines }}" + + - name: "4.5.1.5 | WARN | Ensure inactive password lock is 30 days or less | Warn Users in future" + when: + - rhel8cis_users_user_future + - rhel8cis_users_user_future.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml diff --git a/tasks/section_4/cis_4.5.2.x.yml b/tasks/section_4/cis_4.5.2.x.yml new file mode 100644 index 00000000..2a743fc9 --- /dev/null +++ b/tasks/section_4/cis_4.5.2.x.yml @@ -0,0 +1,99 @@ +--- + +- name: "4.5.2.1 | PATCH | Ensure default group for the root account is GID 0" + when: + - rhel8cis_rule_4_5_2_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - root + - rule_4.5.2.1 + ansible.builtin.user: + name: root + group: 0 + +- name: "4.5.2.2 | PATCH | Ensure root user umask is configured" + when: + - rhel8cis_rule_4_5_2_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - shadow_suite + - rule_4.5.2.2 + ansible.builtin.lineinfile: + path: /root/.bash_profile + regexp: \s*umask + line: "umask {{ rhel8cis_root_umask }}" + +- name: "4.5.2.3 | PATCH | Ensure system accounts are secured" + when: + - rhel8cis_rule_4_5_2_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-2 + - NIST800-53R5_AC-3 + - NIST800-53R5_AC-11 + - NIST800-53R5_MP-2 + - shadow_suite + - rule_4.5.2.3 + block: + - name: "4.5.2.3 | PATCH | | Ensure system accounts are secured | Set nologin" + when: + - item.id != "root" + - item.id != "sync" + - item.id != "shutdown" + - item.id != "halt" + - item.id != "nfsnobody" + - item.uid < rhel8cis_min_uid | int + - item.shell != " /bin/false" + - item.shell != " /usr/sbin/nologin" + ansible.builtin.user: + name: "{{ item.id }}" + shell: /usr/sbin/nologin + loop: "{{ rhel8cis_passwd }}" + loop_control: + label: "{{ item.id }}" + + - name: "4.5.2.3 | PATCH | | Ensure system accounts are secured | Lock accounts" + when: + - item.id != "root" + - item.id != "sync" + - item.id != "shutdown" + - item.id != "halt" + - item.id != "nfsnobody" + - item.uid < rhel8cis_min_uid | int + - item.shell != " /bin/false" + - item.shell != " /usr/sbin/nologin" + ansible.builtin.user: + name: "{{ item.id }}" + password_lock: true + loop: "{{ rhel8cis_passwd }}" + loop_control: + label: "{{ item.id }}" + +- name: "4.5.2.4 | PATCH | Ensure root password is set" + when: + - rhel8cis_rule_4_5_2_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - shadow_suite + - rule_4.5.2.4 + ansible.builtin.debug: + msg: "This is set as an assert in tasks/main" diff --git a/tasks/section_4/cis_4.5.3.x.yml b/tasks/section_4/cis_4.5.3.x.yml new file mode 100644 index 00000000..ffcde18d --- /dev/null +++ b/tasks/section_4/cis_4.5.3.x.yml @@ -0,0 +1,68 @@ +--- + +- name: "4.5.3.1 | PATCH | Ensure nologin is not listed in /etc/shells" + when: + - rhel8cis_rule_4_5_3_1 + tags: + - level2-server + - level2-workstation + - automated + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - patch + - shells + - rule_4.5.3.1 + ansible.builtin.replace: + path: /etc/shells + regexp: nologin + replace: "" + +- name: "4.5.3.2 | PATCH | Ensure default user shell timeout is configured" + when: + - rhel8cis_rule_4_5_3_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - shell + - rule_4.5.3.2 + ansible.builtin.blockinfile: + path: "{{ item.path }}" + state: "{{ item.state }}" + marker: "# {mark} - CIS benchmark - Ansible-lockdown" + create: true + mode: '0644' + block: | + TMOUT={{ rhel8cis_shell_session_timeout.timeout }} + readonly TMOUT + export TMOUT + loop: + - { path: "{{ rhel8cis_shell_session_timeout.file }}", state: present } + - { path: /etc/profile, state: "{{ (rhel8cis_shell_session_timeout.file == '/etc/profile') | ternary('present', 'absent') }}" } + +- name: "4.5.3.3 | PATCH | Ensure default user umask is configured" + when: + - rhel8cis_rule_4_5_3_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - umask + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.5.3.3 + ansible.builtin.replace: + path: "{{ item.path }}" + regexp: (?i)(umask\s+\d\d\d) + replace: '{{ item.line }} 027' + loop: + - { path: '/etc/bashrc', line: 'umask' } + - { path: '/etc/profile', line: 'umask' } + - { path: '/etc/login.defs', line: 'UMASK' } diff --git a/tasks/section_4/main.yml b/tasks/section_4/main.yml index 4b93685e..2ad47325 100644 --- a/tasks/section_4/main.yml +++ b/tasks/section_4/main.yml @@ -1,27 +1,64 @@ --- -# 4.1 Configure System Accounting (auditd) -- name: "SECTION | 4.1| Ensure auditing is enabled" - ansible.builtin.import_tasks: cis_4.1.1.x.yml +# Access, Authentication, and Authorization + +- name: "SECTION | 4.1.1 | Configure time-based job schedulers | cron" + ansible.builtin.import_tasks: + file: cis_4.1.1.x.yml + +- name: "SECTION | 4.1.2 | Configure job schedulers | at" + ansible.builtin.import_tasks: + file: cis_4.1.2.x.yml + +- name: "SECTION | 4.2 | Configure SSH Server" + ansible.builtin.import_tasks: + file: cis_4.2.x.yml + when: + - "'openssh-server' in ansible_facts.packages" + +- name: "SECTION | 4.3 | Configure privilege escalation" + ansible.builtin.import_tasks: + file: cis_4.3.x.yml + +- name: "SECTION | 4.4.1 | Configure PAM software packages" + ansible.builtin.import_tasks: + file: cis_4.4.1.x.yml + +- name: "SECTION | 4.4.2 | Authselect" when: - - not system_is_container + - rhel8cis_allow_authselect_updates + - rhel8cis_disruption_high + ansible.builtin.import_tasks: + file: cis_4.4.2.x.yml + +- name: "SECTION | 4.4.3.1.x | Configure module pam_faillock" + when: rhel8cis_disruption_high + ansible.builtin.import_tasks: + file: cis_4.4.3.1.x.yml -- name: "SECTION | 4.1.2.x| Configure Data Retention" - ansible.builtin.import_tasks: cis_4.1.2.x.yml +- name: "SECTION | 4.4.3.2.x | Configure module pam_pwquality" + when: rhel8cis_disruption_high + ansible.builtin.import_tasks: + file: cis_4.4.3.2.x.yml -- name: "SECTION | 4.1.3.x| Configure auditd rules" - ansible.builtin.import_tasks: cis_4.1.3.x.yml +- name: "SECTION | 4.4.3.3.x | Configure module pam_pwhistory" + when: rhel8cis_disruption_high + ansible.builtin.import_tasks: + file: cis_4.4.3.3.x.yml -# 4.2 Configure Logging -- name: "SECTION | 4.2.1.x| Configure rsyslog" - ansible.builtin.import_tasks: cis_4.2.1.x.yml - when: rhel8cis_syslog == 'rsyslog' +- name: "SECTION | 4.4.3.4.x | Configure module pam_unix" + when: rhel8cis_disruption_high + ansible.builtin.import_tasks: + file: cis_4.4.3.4.x.yml -- name: "SECTION | 4.2.2.x| Configure journald" - ansible.builtin.import_tasks: cis_4.2.2.x.yml +- name: "SECTION | 4.5.1.x | Shadow suite" + ansible.builtin.import_tasks: + file: cis_4.5.1.x.yml -- name: "SECTION | 4.2.3 | Configure logile perms" - ansible.builtin.import_tasks: cis_4.2.3.yml +- name: "SECTION | 4.5.2.x | Root and sys accounts" + ansible.builtin.import_tasks: + file: cis_4.5.2.x.yml -- name: "SECTION | 4.3 | Configure logrotate" - ansible.builtin.import_tasks: cis_4.3.yml +- name: "SECTION | 4.5.3.x | User enviroment" + ansible.builtin.import_tasks: + file: cis_4.5.3.x.yml diff --git a/tasks/section_4/cis_4.2.1.x.yml b/tasks/section_5/cis_5.1.1.x.yml similarity index 60% rename from tasks/section_4/cis_4.2.1.x.yml rename to tasks/section_5/cis_5.1.1.x.yml index a2dfba43..c0856616 100644 --- a/tasks/section_4/cis_4.2.1.x.yml +++ b/tasks/section_5/cis_5.1.1.x.yml @@ -1,84 +1,103 @@ --- -- name: "4.2.1.1 | PATCH | Ensure rsyslog installed" - ansible.builtin.package: - name: rsyslog - state: present +- name: "5.1.1.1 | PATCH | Ensure rsyslog installed" when: - "'rsyslog' not in ansible_facts.packages" - - rhel8cis_rule_4_2_1_1 + - rhel8cis_rule_5_1_1_1 tags: - level1-server - level1-workstation - - automated - patch - rsyslog - - rule_4.2.1.1 - -- name: "4.2.1.2 | PATCH | Ensure rsyslog Service is enabled" - ansible.builtin.service: + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - rule_5.1.1.1 + ansible.builtin.package: name: rsyslog - enabled: true + state: present + +- name: "5.1.1.2 | PATCH | Ensure rsyslog service is enabled" when: - - rhel8cis_rule_4_2_1_2 + - rhel8cis_rule_5_1_1_2 tags: - level1-server - level1-workstation - - automated - patch - rsyslog - - rule_4.2.1.2 + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + - rule_5.1.1.2 + ansible.builtin.systemd: + name: rsyslog + enabled: true -# This is counter to control 4.2.1.5?? -- name: "4.2.1.3 | PATCH | Ensure journald is configured to send logs to rsyslog" +- name: "5.1.1.3 | PATCH | Ensure journald is configured to send logs to rsyslog" ansible.builtin.lineinfile: path: /etc/systemd/journald.conf regexp: "^#ForwardToSyslog=|^ForwardToSyslog=" line: ForwardToSyslog=yes + notify: Restart_journald when: - - rhel8cis_rule_4_2_1_3 + - rhel8cis_rule_5_1_1_3 + - rhel8cis_syslog == "rsyslog" tags: - level1-server - level1-workstation - - manual - patch - - rule_4.2.1.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-4 + - NIST800-53R5_AU-12 + - NIST800-53R5_MP-2 + - NIST800-53R5_SI-5 + - rsyslog + - rule_5.1.1.3 -- name: "4.2.1.4 | PATCH | Ensure rsyslog default file permissions configured" +- name: "5.1.1.4 | PATCH | Ensure rsyslog default file permissions configured" + when: + - rhel8cis_rule_5_1_1_4 + tags: + - level1-server + - level1-workstation + - patch + - rsyslog + - rule_5.1.1.4 + notify: Restart_rsyslog ansible.builtin.lineinfile: path: /etc/rsyslog.conf regexp: '^\$FileCreateMode' line: '$FileCreateMode 0640' - notify: restart rsyslog + +- name: "5.1.1.5 | PATCH | Ensure logging is configured" when: - - rhel8cis_rule_4_2_1_4 + - rhel8cis_rule_5_1_1_5 tags: - level1-server - level1-workstation - - automated - patch - rsyslog - - rule_4.2.1.4 - -- name: "4.2.1.5 | PATCH | Ensure logging is configured" + - rule_5.1.1.5 + notify: Restart_rsyslog block: - - name: "4.2.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out" + - name: "5.1.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out" ansible.builtin.shell: cat /etc/rsyslog.conf changed_when: false failed_when: false check_mode: false - register: rhel_08_4_2_1_5_audit + register: rhel_09_5_1_1_5_audit - - name: "4.2.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out" + - name: "5.1.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out" ansible.builtin.debug: msg: - "These are the current logging configurations for rsyslog, please review:" - - "{{ rhel_08_4_2_1_5_audit.stdout_lines }}" + - "{{ rhel_09_5_1_1_5_audit.stdout_lines }}" - - name: "4.2.1.5 | PATCH | Ensure logging is configured | mail.* log setting" + - name: "5.1.1.5 | PATCH | Ensure logging is configured | mail.* log setting" + when: rhel8cis_rsyslog_ansiblemanaged ansible.builtin.blockinfile: path: /etc/rsyslog.conf - marker: "# {mark} MAIL LOG SETTINGS (ANSIBLE MANAGED)" + marker: "# {mark} MAIL LOG SETTINGS - CIS benchmark - Ansible-lockdown" block: | # mail logging additions to meet CIS standards mail.* -/var/log/mail @@ -86,41 +105,25 @@ mail.warning -/var/log/mail.warning mail.err /var/log/mail.err insertafter: '# Log all the mail messages in one place.' - notify: restart rsyslog - when: rhel8cis_rsyslog_ansiblemanaged - - name: "4.2.1.5 | PATCH | Ensure logging is configured | news.crit log setting" - ansible.builtin.blockinfile: - path: /etc/rsyslog.conf - state: present - marker: "# {mark} NEWS LOG SETTINGS (ANSIBLE MANAGED)" - block: | - # news logging additions to meet CIS standards - news.crit -/var/log/news/news.crit - news.notice -/var/log/news/news.crit - insertafter: '# Save news errors of level crit and higher in a special file.' - notify: restart rsyslog + - name: "5.1.1.5 | PATCH | Ensure logging is configured | Misc. log setting" when: rhel8cis_rsyslog_ansiblemanaged - - - name: "4.2.1.5 | PATCH | Ensure logging is configured | Misc. log setting" ansible.builtin.blockinfile: path: /etc/rsyslog.conf state: present - marker: "# {mark} MISC. LOG SETTINGS (ANSIBLE MANAGED)" + marker: "# {mark} MISC. LOG SETTINGS - CIS benchmark - Ansible-lockdown" block: | # misc. logging additions to meet CIS standards *.=warning;*.=err -/var/log/warn *.crit /var/log/warn *.*;mail.none;news.none /var/log/messages insertafter: '#### RULES ####' - notify: restart rsyslog - when: rhel8cis_rsyslog_ansiblemanaged - - name: "4.2.1.5 | PATCH | Ensure logging is configured | Local log settings" + - name: "5.1.1.5 | PATCH | Ensure logging is configured | Local log settings" ansible.builtin.blockinfile: path: /etc/rsyslog.conf state: present - marker: "#{mark} LOCAL LOG SETTINGS (ANSIBLE MANAGED)" + marker: "#{mark} LOCAL LOG SETTINGS - CIS benchmark - Ansible-lockdown" block: | # local log settings to meet CIS standards local0,local1.* -/var/log/localmessages @@ -129,96 +132,79 @@ local6,local7.* -/var/log/localmessages *.emerg :omusrmsg:* insertafter: '#### RULES ####' - notify: restart rsyslog - - name: "4.2.1.5 | PATCH | Ensure logging is configured | Auth Settings" + - name: "5.1.1.5 | PATCH | Ensure logging is configured | Auth Settings" ansible.builtin.blockinfile: path: /etc/rsyslog.conf state: present - marker: "#{mark} Auth SETTINGS (ANSIBLE MANAGED)" + marker: "#{mark} Auth SETTINGS - CIS benchmark - Ansible-lockdown" block: | # Private settings to meet CIS standards - auth,authpriv.* -/var/log/secure + auth,authpriv.* /var/log/secure insertafter: '#### RULES ####' - notify: restart rsyslog - - name: "4.2.1.5 | PATCH | Ensure logging is configured | Cron Settings" + - name: "5.1.1.5 | PATCH | Ensure logging is configured | Cron Settings" ansible.builtin.blockinfile: path: /etc/rsyslog.conf state: present - marker: "#{mark} Cron SETTINGS (ANSIBLE MANAGED)" + marker: "#{mark} Cron SETTINGS - CIS benchmark - Ansible-lockdown" block: | # Cron settings to meet CIS standards cron.* /var/log/cron insertafter: '#### RULES ####' - notify: restart rsyslog + +- name: "5.1.1.6 | PATCH | Ensure rsyslog is configured to send logs to a remote log host" when: - - rhel8cis_rule_4_2_1_5 + - rhel8cis_rule_5_1_1_6 + - rhel8cis_remote_log_server tags: - level1-server - level1-workstation - - manual - patch - rsyslog - - rule_4.2.1.5 - -- name: "4.2.1.6 | PATCH | Ensure rsyslog is configured to send logs to a remote log host" + - rule_5.1.1.6 + notify: Restart_rsyslog ansible.builtin.blockinfile: path: /etc/rsyslog.conf state: present block: | - # remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional - *.* @@{{ rhel8cis_remote_log_server }} + # target can be IP or FQDN + *.* action(type="omfwd" target="{{ rhel8cis_remote_log_host }}" port="{{ rhel8cis_remote_log_port }}" protocol="{{ rhel8cis_remote_log_protocol }}" action.resumeRetryCount="{{ rhel8cis_remote_log_retrycount }}" queue.type="LinkedList" queue.size="{{ rhel8cis_remote_log_queuesize }}") insertafter: EOF register: result failed_when: - result is failed - result.rc != 257 - notify: restart rsyslog + +- name: "5.1.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client" when: - - rhel8cis_rule_4_2_1_6 - - rhel8cis_remote_log_server is defined + - rhel8cis_rule_5_1_1_7 tags: - level1-server - level1-workstation - - manual - patch - rsyslog - - rule_4.2.1.6 - -- name: "4.2.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client" + - rule_5.1.1.7 + notify: Restart_rsyslog block: - - name: "4.2.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client. | When not log host" + - name: "5.1.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client. | When not log host" + when: not rhel8cis_system_is_log_server ansible.builtin.replace: path: /etc/rsyslog.conf - regexp: '({{ item }})' + regexp: '{{ item }}' replace: '#\1' - notify: restart rsyslog - with_items: + loop: - '^(\$ModLoad imtcp)' - '^(\$InputTCPServerRun)' - '^(module\(load="imtcp"\))' - '^(input\(type="imtcp")' - when: not rhel8cis_system_is_log_server - - name: "4.2.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote clients. | When log host" + - name: "5.1.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote clients. | When log host" + when: rhel8cis_system_is_log_server ansible.builtin.replace: path: /etc/rsyslog.conf regexp: '^#(.*{{ item }}.*)' replace: '\1' - notify: restart rsyslog - with_items: + loop: - 'ModLoad imtcp' - 'InputTCPServerRun' - - 'module\(load="imtcp"\)' - - 'input\(type="imtcp"' - when: rhel8cis_system_is_log_server - when: - - rhel8cis_rule_4_2_1_7 - tags: - - level1-server - - level1-workstation - - automated - - patch - - rsyslog - - rule_4.2.1.7 diff --git a/tasks/section_4/cis_4.2.2.x.yml b/tasks/section_5/cis_5.1.2.x.yml similarity index 52% rename from tasks/section_4/cis_4.2.2.x.yml rename to tasks/section_5/cis_5.1.2.x.yml index 269a7d01..6f5e224c 100644 --- a/tasks/section_4/cis_4.2.2.x.yml +++ b/tasks/section_5/cis_5.1.2.x.yml @@ -1,131 +1,152 @@ --- -- name: "4.2.2.1.1 | PATCH | Ensure systemd-journal-remote is installed" +- name: "5.1.2.1.1 | PATCH | Ensure systemd-journal-remote is installed" + when: + - rhel8cis_rule_5_1_2_1_1 + - rhel8cis_syslog == 'journald' + tags: + - level1-server + - level1-workstation + - manual + - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - journald + - rule_5.1.2.1.1 ansible.builtin.package: name: systemd-journal-remote state: present + +- name: "5.1.2.1.2 | PATCH | Ensure systemd-journal-remote is configured" when: - - rhel8cis_rule_4_2_2_1_1 + - rhel8cis_rule_5_1_2_1_2 - rhel8cis_syslog == 'journald' tags: - level1-server - level1-workstation - manual - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 - journald - - rule_4.2.2.1.1 - -- name: "4.2.2.1.2 | PATCH | Ensure systemd-journal-remote is configured" + - rule_5.1.2.1.2 + notify: Restart_systemd_journal_upload ansible.builtin.lineinfile: path: /etc/systemd/journal-upload.conf regexp: "{{ item.regexp }}" line: "{{ item.line }}" - notify: restart systemd_journal_upload - with_items: + loop: - { regexp: 'URL=', line: 'URL={{ rhel8cis_journal_upload_url }}'} - { regexp: 'ServerKeyFile=', line: 'ServerKeyFile={{ rhel8cis_journal_upload_serverkeyfile }}'} - { regexp: 'ServerCertificateFile=', line: 'ServerCertificateFile={{ rhel8cis_journal_servercertificatefile }}'} - { regexp: 'TrustedCertificateFile=', line: 'TrustedCertificateFile={{ rhel8cis_journal_trustedcertificatefile }}'} + +- name: "5.1.2.1.3 | PATCH | Ensure systemd-journal-remote is enabled" when: - - rhel8cis_rule_4_2_2_1_2 + - rhel8cis_system_is_log_server + - rhel8cis_rule_5_1_2_1_3 - rhel8cis_syslog == 'journald' tags: - level1-server - level1-workstation - - manual + - automated - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 - journald - - rule_4.2.2.1.2 - -- name: "4.2.2.1.3 | PATCH | Ensure systemd-journal-remote is enabled" + - rule_5.1.2.1.3 ansible.builtin.systemd: name: systemd-journal-upload state: started enabled: true + +- name: "5.1.2.1.4 | PATCH | Ensure journald is not configured to recieve logs from a remote client" when: - - rhel8cis_system_is_log_server - - rhel8cis_rule_4_2_2_1_3 + - not rhel8cis_system_is_log_server + - rhel8cis_rule_5_1_2_1_4 - rhel8cis_syslog == 'journald' tags: - level1-server - level1-workstation - - manual + - automated - patch - journald - - rule_4.2.2.1.3 - -- name: "4.2.2.1.4 | PATCH | Ensure journald is not configured to recieve logs from a remote client" + - rule_5.1.2.1.4 ansible.builtin.systemd: name: systemd-journal-remote.socket state: stopped enabled: false masked: true + +- name: "5.1.2.2 | PATCH | Ensure journald service is enabled" when: - - not rhel8cis_system_is_log_server - - rhel8cis_rule_4_2_2_1_4 + - rhel8cis_rule_5_1_2_2 - rhel8cis_syslog == 'journald' tags: - level1-server - level1-workstation - automated - - patch + - audit - journald - - rule_4.2.2.1.4 - -- name: "4.2.2.2 | PATCH | Ensure journald service is enabled" + - rule_5.1.2.2 block: - - name: "4.2.2.2 | PATCH | Ensure journald service is enabled | Enable service" + - name: "5.1.2.2 | PATCH | Ensure journald service is enabled | Enable service" ansible.builtin.systemd: name: systemd-journald state: started enabled: true - - name: "4.2.2.2 | AUDIT | Ensure journald service is enabled | Capture status" + - name: "5.1.2.2 | AUDIT | Ensure journald service is enabled | Capture status" ansible.builtin.shell: systemctl is-enabled systemd-journald.service changed_when: false failed_when: false - register: rhel8cis_4_2_2_2_status + register: rhel8cis_5_1_2_2_status - - name: "4.2.2.2 | AUDIT | Ensure journald service is enabled | Alert on bad status" + - name: "5.1.2.2 | AUDIT | Ensure journald service is enabled | Alert on bad status" ansible.builtin.debug: msg: - "Warning!! The status of systemd-journald should be static and it is not. Please investigate" - when: "'static' not in rhel8cis_4_2_2_2_status.stdout" + when: "'static' not in rhel8cis_5_1_2_2_status.stdout" - - name: "4.2.2.2 | AUDIT | Ensure journald service is enabled | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml + - name: "5.1.2.2 | AUDIT | Ensure journald service is enabled | Warn Count" + ansible.builtin.import_tasks: + file: warning_facts.yml vars: - warn_control_id: '4.2.2.2' - when: "'static' not in rhel8cis_4_2_2_2_status.stdout" + warn_control_id: '5.1.2.2' + when: "'static' not in rhel8cis_5_1_2_2_status.stdout" + +- name: "5.1.2.3 | PATCH | Ensure journald is configured to compress large log files" when: - - rhel8cis_rule_4_2_2_2 - - rhel8cis_syslog == 'journald' + - rhel8cis_rule_5_1_2_3 tags: - level1-server - level1-workstation - automated - - audit + - patch - journald - - rule_4.2.2.2 - -- name: "4.2.2.3 | PATCH | Ensure journald is configured to compress large log files" + - rule_5.1.2.3 + notify: Restart_journald ansible.builtin.lineinfile: path: /etc/systemd/journald.conf regexp: 'Compress=' line: Compress=yes insertafter: ^#Compress validate: /usr/bin/bash -n %s + +- name: "5.1.2.4 | PATCH | Ensure journald is configured to write logfiles to persistent disk" when: - - rhel8cis_rule_4_2_2_3 + - rhel8cis_rule_5_1_2_4 tags: - level1-server - level1-workstation - automated - patch - journald - - rule_4.2.2.3 - -- name: "4.2.2.4 | PATCH | Ensure journald is configured to write logfiles to persistent disk" + - rule_5.1.2.4 + notify: Restart_journald ansible.builtin.lineinfile: path: /etc/systemd/journald.conf regexp: 'Storage=' @@ -133,96 +154,44 @@ state: present insertafter: ^#Storage validate: /usr/bin/bash -n %s + +# This is counter to control 5.1.1.3?? +- name: "5.1.2.5 | PATCH | Ensure journald is not configured to send logs to rsyslog" when: - - rhel8cis_rule_4_2_2_4 + - rhel8cis_rule_5_1_2_5 + - rhel8cis_syslog == 'journald' tags: - level1-server - - level1-workstation - - automated + - level2-workstation + - manual - patch - journald - - rule_4.2.2.4 - -# This is counter to control 4.2.1.3?? -- name: "4.2.2.5 | PATCH | Ensure journald is not configured to send logs to rsyslog" + - rule_5.1.2.5 + notify: Restart_journald ansible.builtin.lineinfile: path: /etc/systemd/journald.conf regexp: "^ForwardToSyslog=" line: "#ForwardToSyslog=yes" - notify: restart systemd_journal_upload + +- name: "5.1.2.6 | PATCH | Ensure journald log rotation is configured per site policy" when: - - rhel8cis_rule_4_2_2_5 + - rhel8cis_rule_5_1_2_6 - rhel8cis_syslog == 'journald' tags: - level1-server - - level2-workstation + - level1-workstation - manual - patch - journald - - rule_4.2.2.5 - -- name: "4.2.2.6 | PATCH | Ensure journald log rotation is configured per site policy" + - rule_5.1.2.6 ansible.builtin.lineinfile: path: /etc/systemd/journald.conf regexp: "{{ item.regexp }}" line: "{{ item.line }}" - notify: restart journald - with_items: + notify: Restart_journald + loop: - { regexp: '^#SystemMaxUse=|^SystemMaxUse=', line: 'SystemMaxUse={{ rhel8cis_journald_systemmaxuse }}'} - { regexp: '^#SystemKeepFree=|^SystemKeepFree=', line: 'SystemKeepFree={{ rhel8cis_journald_systemkeepfree }}' } - { regexp: '^#RuntimeMaxUse=|^RuntimeMaxUse=', line: 'RuntimeMaxUse={{ rhel8cis_journald_runtimemaxuse }}'} - { regexp: '^#RuntimeKeepFree=|^RuntimeKeepFree=', line: 'RuntimeKeepFree={{ rhel8cis_journald_runtimekeepfree }}'} - { regexp: '^#MaxFileSec=|^MaxFileSec=', line: 'MaxFileSec={{ rhel8cis_journald_maxfilesec }}'} - when: - - rhel8cis_rule_4_2_2_6 - - rhel8cis_syslog == 'journald' - tags: - - level1-server - - level1-workstation - - manual - - patch - - journald - - rule_4.2.2.6 - -- name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured" - block: - - name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Check for override file" - ansible.builtin.find: - paths: /etc/tmpfiles.d - patterns: systemd.conf - register: rhel8cis_4_2_2_7_override_status - - - name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Get override file settings" - ansible.builtin.shell: cat /etc/tmpfiles.d/systemd.conf - changed_when: false - failed_when: false - register: rhel8cis_4_2_2_7_override_settings - when: rhel8cis_4_2_2_7_override_status.matched >= 1 - - - name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Get non-override file settings" - ansible.builtin.shell: cat /usr/lib/tmpfiles.d/systemd.conf - changed_when: false - failed_when: false - register: rhel8cis_4_2_2_7_notoverride_settings - when: rhel8cis_4_2_2_7_override_status.matched == 0 - - - name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Display file settings" - ansible.builtin.debug: - msg: - - "Warning!! Below are the current default settings for journald, please confirm they align with your site policies" - - "{{ (rhel8cis_4_2_2_7_override_status.matched >= 1) | ternary(rhel8cis_4_2_2_7_override_settings.stdout_lines, rhel8cis_4_2_2_7_notoverride_settings.stdout_lines) }}" - - - name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '4.2.2.7' - when: - - rhel8cis_rule_4_2_2_7 - - rhel8cis_syslog == 'journald' - tags: - - level1-server - - level1-workstation - - manual - - patch - - journald - - rule_4.2.2.7 diff --git a/tasks/section_5/cis_5.1.3.yml b/tasks/section_5/cis_5.1.3.yml new file mode 100644 index 00000000..17d54768 --- /dev/null +++ b/tasks/section_5/cis_5.1.3.yml @@ -0,0 +1,30 @@ +--- + +- name: "5.1.3 | PATCH | Ensure logrotate is configured" + when: + - rhel8cis_rule_5_1_3 + tags: + - level1-server + - level1-workstation + - manual + - patch + - logrotate + - rule_5.1.3 + block: + - name: "5.1.3 | AUDIT | Ensure logrotate is configured | Get logrotate settings" + ansible.builtin.find: + paths: /etc/logrotate.d/ + register: rhel8cis_log_rotate_conf + + - name: "5.1.3 | PATCH | Ensure logrotate is configured | conf files" + ansible.builtin.replace: + path: "{{ item.path }}" + regexp: '^(\s*)(daily|weekly|monthly|yearly)$' + replace: "\\1{{ rhel8cis_logrotate }}" + loop: "{{ rhel8cis_log_rotate_conf.files }}" + + - name: "5.1.3 | PATCH | Ensure logrotate is configured | logrotate.conf" + ansible.builtin.replace: + path: /etc/logrotate.conf + regexp: '^(\s*)(daily|weekly|monthly|yearly)$' + replace: "\\1{{ rhel8cis_logrotate }}" diff --git a/tasks/section_5/cis_5.1.4.yml b/tasks/section_5/cis_5.1.4.yml new file mode 100644 index 00000000..f646d749 --- /dev/null +++ b/tasks/section_5/cis_5.1.4.yml @@ -0,0 +1,37 @@ +--- + +- name: "5.1.4 | PATCH | Ensure permissions on all logfiles are configured" + when: + - rhel8cis_rule_5_1_4 + tags: + - level1-server + - level1-workstation + - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - logfiles + - rule_5.1.4 + block: + - name: "5.1.4 | AUDIT | Ensure permissions on all logfiles are configured | find files" + ansible.builtin.shell: find /var/log/ -type f -perm /g+wx,o+rwx -exec ls {} \; + changed_when: false + failed_when: false + register: rhel8cis_5_1_4_logfiles + + - name: "5.1.4 | AUDIT | Ensure permissions on all logfiles are configured | set_fact" + ansible.builtin.set_fact: + rhel8cis_4_2_3_logfiles_flattened: "{{ rhel8cis_5_1_4_logfiles | json_query('stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] + when: + - rhel8cis_5_1_4_logfiles.stdout_lines | length > 0 + - rhel8cis_5_1_4_logfiles is defined + + - name: "5.1.4 | PATCH | Ensure permissions on all logfiles are configured | change permissions" + ansible.builtin.file: + path: "{{ item }}" + mode: '0640' + loop: "{{ rhel8cis_5_1_4_logfiles_flattened }}" + when: + - rhel8cis_5_1_4_logfiles_flattened is defined + - item != "/var/log/btmp" + - item != "/var/log/utmp" + - item != "/var/log/wtmp" diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml deleted file mode 100644 index 80503035..00000000 --- a/tasks/section_5/cis_5.1.x.yml +++ /dev/null @@ -1,171 +0,0 @@ ---- - -- name: "5.1.1 | PATCH | Ensure cron daemon is enabled" - ansible.builtin.service: - name: crond - enabled: true - when: - - rhel8cis_rule_5_1_1 - tags: - - level1-server - - level1-workstation - - automated - - patch - - cron - - rule_5.1.1 - -- name: "5.1.2 | PATCH | Ensure permissions on /etc/crontab are configured" - ansible.builtin.file: - path: /etc/crontab - owner: root - group: root - mode: 0600 - when: - - rhel8cis_rule_5_1_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - cron - - rule_5.1.2 - -- name: "5.1.3 | PATCH | Ensure permissions on /etc/cron.hourly are configured" - ansible.builtin.file: - path: /etc/cron.hourly - state: directory - owner: root - group: root - mode: 0700 - when: - - rhel8cis_rule_5_1_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - cron - - rule_5.1.3 - -- name: "5.1.4 | PATCH | Ensure permissions on /etc/cron.daily are configured" - ansible.builtin.file: - path: /etc/cron.daily - state: directory - owner: root - group: root - mode: 0700 - when: - - rhel8cis_rule_5_1_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - cron - - rule_5.1.4 - -- name: "5.1.5 | PATCH | Ensure permissions on /etc/cron.weekly are configured" - ansible.builtin.file: - path: /etc/cron.weekly - state: directory - owner: root - group: root - mode: 0700 - when: - - rhel8cis_rule_5_1_5 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.1.5 - -- name: "5.1.6 | PATCH | Ensure permissions on /etc/cron.monthly are configured" - ansible.builtin.file: - path: /etc/cron.monthly - state: directory - owner: root - group: root - mode: 0700 - when: - - rhel8cis_rule_5_1_6 - tags: - - level1-server - - level1-workstation - - automated - - patch - - rule_5.1.6 - -- name: "5.1.7 | PATCH | Ensure permissions on /etc/cron.d are configured" - ansible.builtin.file: - path: /etc/cron.d - state: directory - owner: root - group: root - mode: 0700 - when: - - rhel8cis_rule_5_1_7 - tags: - - level1-server - - level1-workstation - - automated - - patch - - cron - - rule_5.1.7 - -- name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users" - block: - - name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users | Remove cron.deny" - ansible.builtin.file: - path: /etc/cron.deny - state: absent - - - name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users | Check if cron.allow exists" - ansible.builtin.stat: - path: "/etc/cron.allow" - register: rhel8cis_5_1_8_cron_allow_state - - - name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users | Ensure cron.allow is restricted to authorized users" - ansible.builtin.file: - path: /etc/cron.allow - state: '{{ "file" if rhel8cis_5_1_8_cron_allow_state.stat.exists else "touch" }}' - owner: root - group: root - mode: 0600 - when: - - rhel8cis_rule_5_1_8 - tags: - - level1-server - - level1-workstation - - automated - - patch - - cron - - rule_5.1.8 - -- name: "5.1.9 | PATCH | Ensure at is restricted to authorized users" - block: - - name: "5.1.9 | PATCH | Ensure at is restricted to authorized users | Remove at.deny" - ansible.builtin.file: - path: /etc/at.deny - state: absent - - - name: "5.1.9 | PATCH | Ensure at is restricted to authorized users | Check if at.allow exists" - ansible.builtin.stat: - path: "/etc/at.allow" - register: rhel8cis_5_1_9_at_allow_state - - - name: "5.1.9 | PATCH | Ensure at is restricted to authorized users | Ensure at.allow is restricted to authorized users" - ansible.builtin.file: - path: /etc/at.allow - state: '{{ "file" if rhel8cis_5_1_9_at_allow_state.stat.exists else "touch" }}' - owner: root - group: root - mode: 0600 - when: - - rhel8cis_rule_5_1_9 - tags: - - level1-server - - level1-workstation - - automated - - patch - - cron - - rule_5.1.9 diff --git a/tasks/section_5/cis_5.2.1.x.yml b/tasks/section_5/cis_5.2.1.x.yml new file mode 100644 index 00000000..13caa3f5 --- /dev/null +++ b/tasks/section_5/cis_5.2.1.x.yml @@ -0,0 +1,117 @@ +--- + +- name: "5.2.1.1 | PATCH | Ensure auditd is installed" + when: + - rhel8cis_rule_5_2_1_1 + tags: + - level2-server + - level2-workstation + - automated + - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - auditd + - rule_5.2.1.1 + block: + - name: "5.2.1.1 | PATCH | Ensure auditd is installed | Install auditd packages" + ansible.builtin.package: + name: audit + state: present + when: '"auditd" not in ansible_facts.packages' + + - name: "5.2.1.1 | PATCH | Ensure auditd is installed | Install auditd-lib packages" + ansible.builtin.package: + name: audit-libs + state: present + when: '"auditd-lib" not in ansible_facts.packages' + +- name: "5.2.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled" + when: + - rhel8cis_rule_5_2_1_2 + tags: + - level2-server + - level2-workstation + - automated + - patch + - auditd + - grub + - rule_5.2.1.2 + notify: Rebuild_grub + block: + - name: "5.2.1.2 | AUDIT | Ensure auditing for processes that start prior to auditd is enabled | Get GRUB_CMDLINE_LINUX" + ansible.builtin.shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//' + changed_when: false + failed_when: false + check_mode: false + register: rhel8cis_5_2_1_2_grub_cmdline_linux + + - name: "5.2.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Replace existing setting" + when: "'audit=' in rhel8cis_5_2_1_2_grub_cmdline_linux.stdout" + ansible.builtin.replace: + path: /etc/default/grub + regexp: 'audit=.' + replace: 'audit=1' + + - name: "5.2.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Add audit setting if missing" + when: "'audit=' not in rhel8cis_5_2_1_2_grub_cmdline_linux.stdout" + ansible.builtin.lineinfile: + path: /etc/default/grub + regexp: '^GRUB_CMDLINE_LINUX=' + line: '{{ rhel8cis_5_2_1_2_grub_cmdline_linux.stdout }} audit=1"' + +- name: "5.2.1.3 | PATCH | Ensure audit_backlog_limit is sufficient" + when: + - rhel8cis_rule_5_2_1_3 + tags: + - level2-server + - level2-workstation + - automated + - patch + - auditd + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - grub + - rule_5.2.1.3 + notify: Rebuild_grub + block: + - name: "5.2.1.3 | AUDIT | Ensure audit_backlog_limit is sufficient | Get GRUB_CMDLINE_LINUX" + ansible.builtin.shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//' + changed_when: false + failed_when: false + check_mode: false + register: rhel8cis_5_2_1_3_grub_cmdline_linux + + - name: "5.2.1.3 | PATCH | Ensure audit_backlog_limit is sufficient | Replace existing setting" + ansible.builtin.replace: + path: /etc/default/grub + regexp: 'audit_backlog_limit=\d+' + replace: 'audit_backlog_limit={{ rhel8cis_audit_back_log_limit }}' + when: "'audit_backlog_limit=' in rhel8cis_5_2_1_3_grub_cmdline_linux.stdout" + + - name: "5.2.1.3 | PATCH | Ensure audit_backlog_limit is sufficient | Add audit_backlog_limit setting if missing" + ansible.builtin.lineinfile: + path: /etc/default/grub + regexp: '^GRUB_CMDLINE_LINUX=' + line: '{{ rhel8cis_5_2_1_3_grub_cmdline_linux.stdout }} audit_backlog_limit={{ rhel8cis_audit_back_log_limit }}"' + when: "'audit_backlog_limit=' not in rhel8cis_5_2_1_3_grub_cmdline_linux.stdout" + +- name: "5.2.1.4 | PATCH | Ensure auditd service is enabled" + when: + - rhel8cis_rule_5_2_1_4 + tags: + - level2-server + - level2-workstation + - automated + - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - auditd + - rule_5.2.1.4 + ansible.builtin.service: + name: auditd + state: started + enabled: true diff --git a/tasks/section_5/cis_5.2.2.x.yml b/tasks/section_5/cis_5.2.2.x.yml new file mode 100644 index 00000000..f00ad44e --- /dev/null +++ b/tasks/section_5/cis_5.2.2.x.yml @@ -0,0 +1,81 @@ +--- + +- name: "5.2.2.1 | PATCH | Ensure audit log storage size is configured" + when: + - rhel8cis_rule_5_2_2_1 + tags: + - level2-server + - level2-workstation + - automated + - patch + - NIST800-53R5_AU-8 + - auditd + - rule_5.2.2.1 + notify: Restart_auditd + ansible.builtin.lineinfile: + path: /etc/audit/auditd.conf + regexp: ^max_log_file(\s|=) + line: "max_log_file = {{ rhel8cis_max_log_file_size }}" + +- name: "5.2.2.2 | PATCH | Ensure audit logs are not automatically deleted" + when: + - rhel8cis_rule_5_2_2_2 + tags: + - level2-server + - level2-workstation + - automated + - patch + - NIST800-53R5_AU-8 + - auditd + - rule_5.2.2.2 + notify: Restart_auditd + ansible.builtin.lineinfile: + path: /etc/audit/auditd.conf + regexp: "^max_log_file_action" + line: "max_log_file_action = {{ rhel8cis_auditd['max_log_file_action'] }}" + +- name: "5.2.2.3 | PATCH | Ensure system is disabled when audit logs are full" + when: + - rhel8cis_rule_5_2_2_3 + tags: + - level2-server + - level2-workstation + - automated + - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-8 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - auditd + - rule_5.2.2.3 + ansible.builtin.lineinfile: + path: /etc/audit/auditd.conf + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + notify: Restart_auditd + loop: + - { regexp: '^disk_full_action', line: 'disk_full_action = {{ rhel8cis_auditd.disk_full_action }}' } + - { regexp: '^disk_error_action', line: 'disk_error_action = {{ rhel8cis_auditd.disk_error_action }}' } + +- name: "5.2.2.4 | PATCH | Ensure system warns when audit logs are low on space" + when: + - rhel8cis_rule_5_2_2_4 + tags: + - level2-server + - level2-workstation + - automated + - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-8 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - auditd + - rule_5.2.2.4 + ansible.builtin.lineinfile: + path: /etc/audit/auditd.conf + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + notify: Restart_auditd + loop: + - { regexp: '^admin_space_left_action', line: 'admin_space_left_action = {{ rhel8cis_auditd.admin_space_left_action }}' } + - { regexp: '^space_left_action', line: 'space_left_action = {{ rhel8cis_auditd.space_left_action }}' } diff --git a/tasks/section_4/cis_4.1.3.x.yml b/tasks/section_5/cis_5.2.3.x.yml similarity index 63% rename from tasks/section_4/cis_4.1.3.x.yml rename to tasks/section_5/cis_5.2.3.x.yml index 184912c9..6875114b 100644 --- a/tasks/section_4/cis_4.1.3.x.yml +++ b/tasks/section_5/cis_5.2.3.x.yml @@ -1,291 +1,299 @@ --- -- name: "4.1.3.1 | PATCH | Ensure changes to system administration scope (sudoers) is collected" +- name: "5.2.3.1 | PATCH | Ensure changes to system administration scope (sudoers) is collected" + when: + - rhel8cis_rule_5_2_3_1 + tags: + - level2-server + - level2-workstation + - automated + - patch + - auditd + - rule_5.2.3.1 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.2 | PATCH | Ensure actions as another user are always logged" when: - - rhel8cis_rule_4_1_3_1 + - rhel8cis_rule_5_2_3_2 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.1 - -- name: "4.1.3.2 | PATCH | Ensure actions as another user are always logged" + - rule_5.2.3.2 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.3 | PATCH | Ensure events that modify the sudo log file are collected" when: - - rhel8cis_rule_4_1_3_2 + - rhel8cis_rule_5_2_3_3 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.2 - -- name: "4.1.3.3 | PATCH | Ensure events that modify the sudo log file are collected" + - rule_5.2.3.3 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.4 | PATCH | Ensure events that modify date and time information are collected" when: - - rhel8cis_rule_4_1_3_3 + - rhel8cis_rule_5_2_3_4 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.3 - -- name: "4.1.3.4 | PATCH | Ensure events that modify date and time information are collected" + - rule_5.2.3.4 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.5 | PATCH | Ensure events that modify the system's network environment are collected" when: - - rhel8cis_rule_4_1_3_4 + - rhel8cis_rule_5_2_3_5 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.4 - -- name: "4.1.3.5 | PATCH | Ensure events that modify the system's network environment are collected" + - rule_5.2.3.5 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.6 | PATCH | Ensure use of privileged commands is collected" when: - - rhel8cis_rule_4_1_3_5 + - rhel8cis_rule_5_2_3_6 tags: - level2-server - level2-workstation - automated - patch + - NIST800-53R5_AU-3 - auditd - - rule_4.1.3.5 - -- name: "4.1.3.6 | PATCH | Ensure use of privileged commands is collected" + - rule_5.2.3.6 block: - - name: "4.1.3.6 | PATCH | Ensure use of privileged commands is collected" + - name: "5.2.3.6 | PATCH | Ensure use of privileged commands is collected" ansible.builtin.shell: for i in $(df | grep '^/dev' | awk '{ print $NF }'); do find $i -xdev -type f -perm /6000 2>/dev/null; done changed_when: false failed_when: false check_mode: false register: priv_procs - - name: "4.1.3.6 | PATCH | Ensure use of privileged commands is collected" + - name: "5.2.3.6 | PATCH | Ensure use of privileged commands is collected" ansible.builtin.set_fact: update_audit_template: true - notify: update auditd - when: - - rhel8cis_rule_4_1_3_6 - tags: - - level2-server - - level2-workstation - - automated - - patch - - auditd - - rule_4.1.3.6 + notify: Update_auditd_rules -- name: "4.1.3.7 | PATCH | Ensure unsuccessful unauthorized file access attempts are collected" +- name: "5.2.3.7 | PATCH | Ensure unsuccessful unauthorized file access attempts are collected" ansible.builtin.set_fact: update_audit_template: true when: - - rhel8cis_rule_4_1_3_7 + - rhel8cis_rule_5_2_3_7 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.7 + - rule_5.2.3_7 -- name: "4.1.3.8 | PATCH | Ensure events that modify user/group information are collected" - ansible.builtin.set_fact: - update_audit_template: true +- name: "5.2.3.8 | PATCH | Ensure events that modify user/group information are collected" when: - - rhel8cis_rule_4_1_3_8 + - rhel8cis_rule_5_2_3_8 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.8 - -- name: "4.1.3.9 | PATCH | Ensure discretionary access control permission modification events are collected" + - rule_5.2.3.8 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.9 | PATCH | Ensure discretionary access control permission modification events are collected" when: - - rhel8cis_rule_4_1_3_9 + - rhel8cis_rule_5_2_3_9 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.9 - -- name: "4.1.3.10 | PATCH | Ensure successful file system mounts are collected" + - rule_5.2.3.9 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.10 | PATCH | Ensure successful file system mounts are collected" when: - - rhel8cis_rule_4_1_3_10 + - rhel8cis_rule_5_2_3_10 tags: - level2-server - level2-workstation - automated - patch + - NIST800-53R5_CM-6 - auditd - - rule_4.1.3.10 - -- name: "4.1.3.11 | PATCH | Ensure session initiation information is collected" + - rule_5.2.3.10 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.11 | PATCH | Ensure session initiation information is collected" when: - - rhel8cis_rule_4_1_3_11 + - rhel8cis_rule_5_2_3_11 tags: - level2-server - level2-workstation - automated - patch + - NIST800-53R5_AU-3 - auditd - - rule_4.1.3.11 - -- name: "4.1.3.12 | PATCH | Ensure login and logout events are collected" + - rule_5.2.3.11 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.12 | PATCH | Ensure login and logout events are collected" when: - - rhel8cis_rule_4_1_3_12 + - rhel8cis_rule_5_2_3_12 tags: - level2-server - level2-workstation - automated - patch + - NIST800-53R5_AU-3 - auditd - - rule_4.1.3.12 - -- name: "4.1.3.13 | PATCH | Ensure file deletion events by users are collected" + - rule_5.2.3.12 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.13 | PATCH | Ensure file deletion events by users are collected" when: - - rhel8cis_rule_4_1_3_13 + - rhel8cis_rule_5_2_3_13 tags: - level2-server - level2-workstation - auditd - patch - - rule_4.1.3.13 - -- name: "4.1.3.14 | PATCH | Ensure events that modify the system's Mandatory Access Controls are collected" + - rule_5.2.3.13 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.14 | PATCH | Ensure events that modify the system's Mandatory Access Controls are collected" when: - - rhel8cis_rule_4_1_3_14 + - rhel8cis_rule_5_2_3_14 tags: - level2-server - level2-workstation - automated - patch + - NIST800-53R5_AU-3 - auditd - - rule_4.1.3.14 - -- name: "4.1.3.15 | PATCH | Ensure successful and unsuccessful attempts to use the chcon command are recorded" + - rule_5.2.3.14 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.15 | PATCH | Ensure successful and unsuccessful attempts to use the chcon command are recorded" when: - - rhel8cis_rule_4_1_3_15 + - rhel8cis_rule_5_2_3_15 tags: - level2-server - level2- workstation - automated - patch - auditd - - rule_4.1.3.15 - -- name: "4.1.3.16 | PATCH | Ensure successful and unsuccessful attempts to use the setfacl command are recorded" + - rule_5.2.3.15 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.16 | PATCH | Ensure successful and unsuccessful attempts to use the setfacl command are recorded" when: - - rhel8cis_rule_4_1_3_16 + - rhel8cis_rule_5_2_3_16 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.16 - -- name: "4.1.3.17 | PATCH | Ensure successful and unsuccessful attempts to use the chacl command are recorded" + - rule_5.2.3.16 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.17 | PATCH | Ensure successful and unsuccessful attempts to use the chacl command are recorded" when: - - rhel8cis_rule_4_1_3_17 + - rhel8cis_rule_5_2_3_17 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.17 - -- name: "4.1.3.18 | PATCH | Ensure successful and unsuccessful attempts to use the usermod command are recorded" + - rule_5.2.3.17 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.18 | PATCH | Ensure successful and unsuccessful attempts to use the usermod command are recorded" when: - - rhel8cis_rule_4_1_3_18 + - rhel8cis_rule_5_2_3_18 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.18 - -- name: "4.1.3.19 | PATCH | Ensure kernel module loading and unloading is collected" + - rule_5.2.3.18 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.19 | PATCH | Ensure kernel module loading and unloading is collected" when: - - rhel8cis_rule_4_1_3_19 + - rhel8cis_rule_5_2_3_19 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.19 - -- name: "4.1.3.20 | PATCH | Ensure the audit configuration is immutable" + - rule_5.2.3.19 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.20 | PATCH | Ensure the audit configuration is immutable" when: - - rhel8cis_rule_4_1_3_20 + - rhel8cis_rule_5_2_3_20 tags: - level2-server - level2-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_AU-3 + - NIST800-53R5_MP-2 - auditd - rule_4.1.20 + ansible.builtin.set_fact: + update_audit_template: true -- name: "4.1.3.21 | AUDIT | Ensure the running and on disk configuration is the same" - ansible.builtin.debug: - msg: - - "Please run augenrules --load if you suspect there is a configuration that is not active" +- name: "5.2.3.21 | AUDIT | Ensure the running and on disk configuration is the same" when: - - rhel8cis_rule_4_1_3_21 + - rhel8cis_rule_5_2_3_21 tags: - level2-server - level2-workstation - manual - patch - auditd - - rule_4.1.3.21 + - rule_5.2.3.21 + ansible.builtin.debug: + msg: + - "Please run augenrules --load if you suspect there is a configuration that is not active" -- name: Auditd | 4.1.3 | Auditd controls updated +- name: Auditd | 5.2.3 | Auditd controls updated + when: + - update_audit_template ansible.builtin.debug: msg: "Auditd Controls handled in POST using template - updating /etc/auditd/rules.d/99_auditd.rules" changed_when: false - when: - - update_audit_template diff --git a/tasks/section_5/cis_5.2.4.x.yml b/tasks/section_5/cis_5.2.4.x.yml new file mode 100644 index 00000000..4e00f6c1 --- /dev/null +++ b/tasks/section_5/cis_5.2.4.x.yml @@ -0,0 +1,179 @@ +--- + +- name: "5.2.4.1 | PATCH | Ensure the audit log directory is 0750 or more restrictive" + when: + - rhel8cis_rule_5_2_4_1 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.1 + block: + - name: "5.2.4.1 | AUDIT | Ensure the audit log directory is 0750 or more restrictive | get current permissions" + ansible.builtin.stat: + path: "{{ audit_discovered_logfile.stdout | dirname }}" + register: auditlog_dir + + - name: "5.2.4.1 | PATCH | Ensure the audit log directory is 0750 or more restrictive | set" + ansible.builtin.file: + path: "{{ audit_discovered_logfile.stdout | dirname }}" + state: directory + mode: g-w,o-rwx + +- name: | + "5.2.4.2 | PATCH | Ensure audit log files are mode 0640 or less permissive" + "5.2.4.3 | PATCH | Ensure only authorized users own audit log files" + "5.2.4.4 | PATCH | Ensure only authorized groups are assigned ownership of audit log files" + when: + - rhel8cis_rule_5_2_4_2 or + rhel8cis_rule_5_2_4_3 or + rhel8cis_rule_5_2_4_4 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.2 + - rule_5.2.4.3 + - rule_5.2.4.4 + block: + - name: "5.2.4.2 | AUDIT | Ensure audit log files are mode 0640 or less permissive | discover file" + ansible.builtin.shell: grep ^log_file /etc/audit/auditd.conf | awk '{ print $NF }' + changed_when: false + register: audit_discovered_logfile + + - name: "5.2.4.2 | AUDIT | Ensure audit log files are mode 0640 or less permissive | stat file" + ansible.builtin.stat: + path: "{{ audit_discovered_logfile.stdout }}" + changed_when: false + register: auditd_logfile + + - name: | + "5.2.4.2 | PATCH | Ensure audit log files are mode 0640 or less permissive" + "5.2.4.3 | PATCH | Ensure only authorized users own audit log files" + "5.2.4.4 | PATCH | Ensure only authorized groups are assigned ownership of audit log files" + ansible.builtin.file: + path: "{{ audit_discovered_logfile.stdout }}" + mode: "{% if auditd_logfile.stat.mode != '0600' %}0640{% endif %}" + owner: root + group: root + +- name: "5.2.4.5 | PATCH | Ensure audit configuration files are 640 or more restrictive" + when: + - rhel8cis_rule_5_2_4_5 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.5 + ansible.builtin.file: + path: "{{ item.path }}" + mode: g-wx,o-rwx + loop: "{{ auditd_conf_files.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "5.2.4.6 | PATCH | Ensure audit configuration files are owned by root" + when: + - rhel8cis_rule_5_2_4_6 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.6 + ansible.builtin.file: + path: "{{ item.path }}" + owner: root + loop: "{{ auditd_conf_files.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "5.2.4.7 | PATCH | Ensure audit configuration files belong to group root" + when: + - rhel8cis_rule_5_2_4_7 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.7 + ansible.builtin.file: + path: "{{ item.path }}" + group: root + loop: "{{ auditd_conf_files.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "5.2.4.8 | PATCH | Ensure audit tools are 755 or more restrictive" + when: + - rhel8cis_rule_5_2_4_8 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.8 + block: + - name: "5.2.4.8 | AUDIT | Get audit binary file stat | get current mode" + ansible.builtin.stat: + path: "{{ item }}" + register: "audit_bins" + loop: + - /sbin/auditctl + - /sbin/aureport + - /sbin/ausearch + - /sbin/autrace + - /sbin/auditd + - /sbin/augenrules + + - name: "5.2.4.8 | PATCH | Ensure audit tools are 755 or more restrictive | set if required" + ansible.builtin.file: + path: "{{ item.item }}" + mode: g-w,o-w + loop: "{{ audit_bins.results }}" + loop_control: + label: "{{ item.item }}" + +- name: "5.2.4.9 | PATCH | Ensure audit tools are owned by root" + when: + - rhel8cis_rule_5_2_4_9 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.9 + ansible.builtin.file: + path: "{{ item }}" + owner: root + group: root + loop: + - /sbin/auditctl + - /sbin/aureport + - /sbin/ausearch + - /sbin/autrace + - /sbin/auditd + - /sbin/augenrules + +- name: "5.2.4.10 | PATCH | Ensure audit tools belong to group root" + when: + - rhel8cis_rule_5_2_4_10 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.10 + ansible.builtin.file: + path: "{{ item }}" + group: root + loop: + - /sbin/auditctl + - /sbin/aureport + - /sbin/ausearch + - /sbin/autrace + - /sbin/auditd + - /sbin/augenrules diff --git a/tasks/section_5/cis_5.2.x.yml b/tasks/section_5/cis_5.2.x.yml deleted file mode 100644 index 83469fd8..00000000 --- a/tasks/section_5/cis_5.2.x.yml +++ /dev/null @@ -1,378 +0,0 @@ ---- - -- name: "5.2.1 | Ensure permissions on /etc/ssh/sshd_config are configured" - ansible.builtin.file: - path: /etc/ssh/sshd_config - owner: root - group: root - mode: 0600 - when: - - rhel8cis_rule_5_2_1 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - permissions - - rule_5.2.1 - -- name: "5.2.2 | PATCH | Ensure permissions on SSH private host key files are configured" - block: - - name: "5.2.2 | AUDIT | Ensure permissions on SSH private host key files are configured | Find the SSH private host keys" - ansible.builtin.find: - paths: /etc/ssh - patterns: 'ssh_host_*_key' - recurse: true - file_type: any - register: rhel8cis_5_2_2_ssh_private_host_key - - - name: "5.2.2 | PATCH | Ensure permissions on SSH private host key files are configured | Set permissions on SSH private host keys" - ansible.builtin.file: - path: "{{ item.path }}" - owner: root - group: root - mode: 0600 - with_items: - - "{{ rhel8cis_5_2_2_ssh_private_host_key.files }}" - loop_control: - label: "{{ item.path }}" - when: - - rhel8cis_rule_5_2_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - permissions - - rule_5.2.2 - -- name: "5.2.3 | PATCH | Ensure permissions on SSH public host key files are configured" - block: - - name: "5.2.3 | AUDIT | Ensure permissions on SSH public host key files are configured | Find the SSH public host keys" - ansible.builtin.find: - paths: /etc/ssh - patterns: 'ssh_host_*_key.pub' - recurse: true - file_type: any - register: rhel8cis_5_2_3_ssh_public_host_key - - - name: "5.2.3 | PATCH | Ensure permissions on SSH public host key files are configured | Set permissions on SSH public host keys" - ansible.builtin.file: - path: "{{ item.path }}" - owner: root - group: root - mode: 0644 - with_items: - - "{{ rhel8cis_5_2_3_ssh_public_host_key.files }}" - loop_control: - label: "{{ item.path }}" - when: - - rhel8cis_rule_5_2_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.3 - -- name: "5.2.4 | PATCH | Ensure SSH access is limited" - block: - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for allowusers" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^AllowUsers" - line: AllowUsers {{ rhel8cis_sshd['allowusers'] }} - notify: restart sshd - when: "rhel8cis_sshd['allowusers']|default('') | length > 0" - - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for allowgroups" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^AllowGroups" - line: AllowGroups {{ rhel8cis_sshd['allowgroups'] }} - notify: restart sshd - when: "rhel8cis_sshd['allowgroups']|default('') | length > 0" - - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for denyusers" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^DenyUsers" - line: DenyUsers {{ rhel8cis_sshd['denyusers'] }} - notify: restart sshd - when: "rhel8cis_sshd['denyusers']|default('') | length > 0" - - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for denygroups" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^DenyGroups" - line: DenyGroups {{ rhel8cis_sshd['denygroups'] }} - notify: restart sshd - when: "rhel8cis_sshd['denygroups']|default('') | length > 0" - when: - - rhel8cis_rule_5_2_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.4 - -- name: "5.2.5 | PATCH | Ensure SSH LogLevel is appropriate" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#LogLevel|^LogLevel" - line: 'LogLevel {{ rhel8cis_ssh_loglevel }}' - when: - - rhel8cis_rule_5_2_5 - tags: - - level1-server - - level1-workstation - - automated - - patch - - sshs - - rule_5.2.5 - -- name: "5.2.6 | PATCH | Ensure SSH PAM is enabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#UsePAM|^UsePAM" - line: 'UsePAM yes' - when: - - rhel8cis_rule_5_2_6 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.6 - -- name: "5.2.7 | PATCH | Ensure SSH root login is disabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#PermitRootLogin|^PermitRootLogin" - line: 'PermitRootLogin no' - when: - - rhel8cis_rule_5_2_7 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.7 - -- name: "5.2.8 | PATCH | Ensure SSH HostbasedAuthentication is disabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: ^#HostbasedAuthentication|^HostbasedAuthentication" - line: 'HostbasedAuthentication no' - when: - - rhel8cis_rule_5_2_8 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.8 - -- name: "5.2.9 | PATCH | Ensure SSH PermitEmptyPasswords is disabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#PermitEmptyPasswords|^PermitEmptyPasswords" - line: 'PermitEmptyPasswords no' - when: - - rhel8cis_rule_5_2_9 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.9 - -- name: "5.2.10 | PATCH | Ensure SSH PermitUserEnvironment is disabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#PermitUserEnvironment|^PermitUserEnvironment" - line: 'PermitUserEnvironment no' - when: - - rhel8cis_rule_5_2_10 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.10 - -- name: "5.2.11 | PATCH | Ensure SSH IgnoreRhosts is enabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#IgnoreRhosts|^IgnoreRhosts" - line: 'IgnoreRhosts yes' - when: - - rhel8cis_rule_5_2_11 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.11 - -- name: "5.2.12 | PATCH | Ensure SSH X11 forwarding is disabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#X11Forwarding|^X11Forwarding" - line: 'X11Forwarding no' - when: - - rhel8cis_rule_5_2_12 - tags: - - level2-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.12 - -- name: "5.2.13 | PATCH | Ensure SSH AllowTcpForwarding is disabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#AllowTcpForwarding|^AllowTcpForwarding" - line: 'AllowTcpForwarding no' - when: - - rhel8cis_rule_5_2_13 - tags: - - level2-server - - level2-workstation - - automated - - patch - - ssh - - rule_5.2.13 - -- name: "5.2.14 | PATCH | Ensure system-wide crypto policy is not over-ridden" - block: - - name: "5.2.14 | AUDIT | Ensure system-wide crypto policy is not over-ridden" - ansible.builtin.shell: grep -i '^\s*CRYPTO_POLICY=' /etc/sysconfig/sshd - failed_when: ( crypto_policy_override.rc not in [ 0, 1 ] ) - changed_when: false - register: crypto_policy_override - - - name: "5.2.14 | PATCH | Ensure system-wide crypto policy is not over-ridden" - ansible.builtin.shell: sed -ri "s/^\s*(CRYPTO_POLICY\s*=.*)$/# \1/" /etc/sysconfig/sshd - notify: restart sshd - when: - - crypto_policy_override.stdout | length > 0 - when: - - rhel8cis_rule_5_2_14 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.14 - -- name: "5.2.15 | PATCH | Ensure SSH warning banner is configured" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: '^Banner' - line: 'Banner /etc/issue.net' - when: - - rhel8cis_rule_5_2_15 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.15 - -- name: "5.2.16 | PATCH | Ensure SSH MaxAuthTries is set to 4 or less" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: '^(#)?MaxAuthTries \d' - line: 'MaxAuthTries 4' - when: - - rhel8cis_rule_5_2_16 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.16 - -- name: "5.2.17 | PATCH | Ensure SSH MaxStartups is configured" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#MaxStartups|^MaxStartups" - line: 'MaxStartups 10:30:60' - when: - - rhel8cis_rule_5_2_17 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.17 - -- name: "5.2.18 | PATCH | Ensure SSH MaxSessions is set to 10 or less" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#MaxSessions|^MaxSessions" - line: 'MaxSessions {{ rhel8cis_ssh_maxsessions }}' - when: - - rhel8cis_rule_5_2_18 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.18 - -- name: "5.2.19 | PATCH | Ensure SSH LoginGraceTime is set to one minute or less" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#LoginGraceTime|^LoginGraceTime" - line: "LoginGraceTime {{ rhel8cis_sshd['logingracetime'] }}" - when: - - rhel8cis_rule_5_2_19 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.19 - -- name: "5.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured" - block: - - name: "5.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured | Add line in sshd_config for ClientAliveInterval" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: '^ClientAliveInterval' - line: "ClientAliveInterval {{ rhel8cis_sshd['clientaliveinterval'] }}" - - - name: "5.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured | Ensure SSH ClientAliveCountMax set to <= 3" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: '^ClientAliveCountMax' - line: "ClientAliveCountMax {{ rhel8cis_sshd['clientalivecountmax'] }}" - when: - - rhel8cis_rule_5_2_20 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.20 diff --git a/tasks/section_5/cis_5.3.x.yml b/tasks/section_5/cis_5.3.x.yml index 72ad599d..e42be413 100644 --- a/tasks/section_5/cis_5.3.x.yml +++ b/tasks/section_5/cis_5.3.x.yml @@ -1,143 +1,96 @@ --- -- name: "5.3.1 | PATCH | Ensure sudo is installed" - ansible.builtin.package: - name: sudo - state: present +- name: "5.3.1 | PATCH | Ensure AIDE is installed" when: + - rhel8cis_config_aide - rhel8cis_rule_5_3_1 tags: - level1-server - level1-workstation - automated + - aide + - NIST800-53R5_AU-2 - patch - - sudo - rule_5.3.1 - -- name: "5.3.2 | PATCH | Ensure sudo commands use pty" - ansible.builtin.lineinfile: - path: /etc/sudoers - line: "Defaults use_pty" - when: - - rhel8cis_rule_5_3_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - sudo - - rule_5.3.2 - -- name: "5.3.3 | PATCH | Ensure sudo log file exists" - ansible.builtin.lineinfile: - path: /etc/sudoers - regexp: '^Defaults\s+logfile=' - line: 'Defaults logfile={{ rhel8cis_sudolog_location }}' - when: - - rhel8cis_rule_5_3_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - sudo - - rule_5.3.3 - -- name: "5.3.4 | PATCH | Ensure users must provide password for escalation" - ansible.builtin.replace: - path: "{{ item }}" - regexp: '^([^#|{% if system_is_ec2 %}ec2-user{% endif %}].*)NOPASSWD(.*)' - replace: '\1PASSWD\2' - with_items: - - "{{ rhel8cis_sudoers_files.stdout_lines }}" - when: - - rhel8cis_rule_5_3_4 - tags: - - level2-server - - level2-workstation - - automated - - patch - - sudo - - rule_5.3.4 - -- name: "5.3.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally" - ansible.builtin.replace: - path: "{{ item }}" - regexp: '^([^#].*)!authenticate(.*)' - replace: '\1authenticate\2' - with_items: - - "{{ rhel8cis_sudoers_files.stdout_lines }}" - when: - - rhel8cis_rule_5_3_5 - tags: - - level1-server - - level1-workstation - - automated - - patch - - sudo - - rule_5.3.5 - -- name: "5.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly" block: - - name: "5.3.6 | AUDIT | Ensure sudo authentication timeout is configured correctly | Get files with timeout set" - ansible.builtin.shell: grep -is 'timestamp_timeout' /etc/sudoers /etc/sudoers.d/* | cut -d":" -f1 | uniq | sort + - name: "5.3.1 | PATCH | Ensure AIDE is installed | Install AIDE" + ansible.builtin.package: + name: aide + state: present + + - name: "5.3.1 | PATCH | Ensure AIDE is installed | Configure AIDE" + ansible.builtin.shell: /usr/sbin/aide --init changed_when: false failed_when: false - register: rhel8cis_5_3_6_timeout_files + async: 45 + poll: 0 + args: + creates: /var/lib/aide/aide.db.new.gz + when: not ansible_check_mode - - name: "5.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if no results" - ansible.builtin.lineinfile: - path: /etc/sudoers - regexp: 'Defaults timestamp_timeout=' - line: "Defaults timestamp_timeout={{ rhel8cis_sudo_timestamp_timeout }}" - validate: '/usr/sbin/visudo -cf %s' - when: rhel8cis_5_3_6_timeout_files.stdout | length == 0 + - name: "5.3.1 | PATCH | Ensure AIDE is installed | copy AIDE DB" + ansible.builtin.copy: + src: /var/lib/aide/aide.db.new.gz + dest: /var/lib/aide/aide.db.gz + remote_src: true - - name: "5.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if has results" - ansible.builtin.replace: - path: "{{ item }}" - regexp: 'timestamp_timeout=(\d+)' - replace: "timestamp_timeout={{ rhel8cis_sudo_timestamp_timeout }}" - validate: '/usr/sbin/visudo -cf %s' - with_items: - - "{{ rhel8cis_5_3_6_timeout_files.stdout_lines }}" - when: rhel8cis_5_3_6_timeout_files.stdout | length > 0 +- name: "5.3.2 | PATCH | Ensure filesystem integrity is regularly checked" when: - - rhel8cis_rule_5_3_6 + - rhel8cis_rule_5_3_2 + - rhel8cis_config_aide + - not system_is_ec2 tags: - level1-server - level1-workstation - automated + - aide + - NIST800-53R5_AU-2 + - file_integrity - patch - - sudo - - rule_5.3.6 - -- name: "5.3.7 | PATCH | Ensure access to the su command is restricted" + - rule_5.3.2 block: - - name: "5.3.7 | PATCH | Ensure access to the su command is restricted | Ensure sugroup exists" - ansible.builtin.group: - name: "{{ rhel8cis_sugroup }}" - state: present - register: rhel8cis_5_3_7_sugroup + - name: "5.3.2 | PATCH | Ensure filesystem integrity is regularly checked | cron" + when: rhel8cis_aide_scan == "cron" + ansible.builtin.cron: + name: Run AIDE integrity check + cron_file: "{{ rhel8cis_aide_cron['cron_file'] }}" + user: "{{ rhel8cis_aide_cron['cron_user'] }}" + minute: "{{ rhel8cis_aide_cron['aide_minute'] | default('0') }}" + hour: "{{ rhel8cis_aide_cron['aide_hour'] | default('5') }}" + day: "{{ rhel8cis_aide_cron['aide_day'] | default('*') }}" + month: "{{ rhel8cis_aide_cron['aide_month'] | default('*') }}" + weekday: "{{ rhel8cis_aide_cron['aide_weekday'] | default('*') }}" + job: "{{ rhel8cis_aide_cron['aide_job'] }}" - - name: "5.3.7 | PATCH | Ensure access to the su command is restricted | remove users from group" - ansible.builtin.lineinfile: - path: /etc/group - regexp: '^{{ rhel8cis_sugroup }}(:.:.*:).*$' - line: '{{ rhel8cis_sugroup }}\g<1>' - backrefs: true + - name: "5.3.2 | PATCH | Ensure filesystem integrity is regularly checked | timer" + when: rhel8cis_aide_scan == "timer" + ansible.builtin.systemd: + name: "{{ item.name }}" + enabled: true + state: "{{ item.state | default(omit)}}" + loop: + - { name: 'aidecheck.service' } + - { name: 'aidecheck.timer', state: started } - - name: "5.3.7 | PATCH | Ensure access to the su command is restricted | Setting pam_wheel to use_uid" - ansible.builtin.lineinfile: - path: /etc/pam.d/su - regexp: '^(#)?auth\s+required\s+pam_wheel\.so' - line: 'auth required pam_wheel.so use_uid group={{ rhel8cis_sugroup }}' +- name: "5.3.3 | Ensure cryptographic mechanisms are used to protect the integrity of audit tools" when: - - rhel8cis_rule_5_3_7 + - rhel8cis_rule_5_3_3 + - not system_is_ec2 tags: - level1-server - level1-workstation - - automated + - aide + - file_integrity - patch - - sudo - - rule_5.3.7 + - rule_5.3.3 + ansible.builtin.blockinfile: + path: /etc/aide.conf + marker: "# {mark} Audit tools - CIS benchmark - Ansible-lockdown" + block: | + /sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512 + /sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512 + /sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512 + /sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512 + /sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512 + /sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512 + validate: aide -D --config %s diff --git a/tasks/section_5/cis_5.4.x.yml b/tasks/section_5/cis_5.4.x.yml deleted file mode 100644 index a300d9f5..00000000 --- a/tasks/section_5/cis_5.4.x.yml +++ /dev/null @@ -1,100 +0,0 @@ ---- - -- name: "5.4.1 | PATCH | Ensure custom authselect profile is used" - block: - - name: "5.4.1 | AUDIT | Ensure custom authselect profile is used | Gather profiles" - ansible.builtin.shell: authselect list | grep custom | awk '{print $2}' - failed_when: false - changed_when: false - check_mode: false - register: rhel8cis_5_4_1_profiles - - - name: "5.4.1 | AUDIT | Ensure custom authselect profile is used | Show profiles" - ansible.builtin.debug: - msg: - - "Below are the current custom profiles" - - "{{ rhel8cis_5_4_1_profiles.stdout_lines }}" - - - name: "5.4.1 | AUDIT | Ensure custom authselect profile is used | see if profile already exists" - ansible.builtin.stat: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}" - register: rhel8cis_5_4_1_auth_select_profile - - - name: "5.4.1 | PATCH | Ensure custom authselect profile is used | Create custom profiles" - ansible.builtin.shell: authselect create-profile {{ rhel8cis_authselect['custom_profile_name'] }} -b {{ rhel8cis_authselect['default_file_to_copy'] }} - when: - - not rhel8cis_5_4_1_auth_select_profile.stat.exists - - rhel8cis_authselect_custom_profile_create - - - name: "5.4.1 | PATCH | Ensure custom authselect profile is used | select custom profiles" - ansible.builtin.shell: authselect select custom/{{ rhel8cis_authselect['custom_profile_name'] }} --force - when: - - rhel8cis_5_4_1_auth_select_profile.stat.exists - - rhel8cis_authselect_custom_profile_create - when: - - rhel8cis_rule_5_4_1 - tags: - - level1-server - - level1-workstation - - manual - - patch - - authselect - - rule_5.4.1 - -- name: "5.4.2 | PATCH | Ensure authselect includes with-faillock" - block: - - name: "5.4.2 | AUDIT | Ensure authselect includes with-faillock | Gather profiles and enabled features" - ansible.builtin.shell: "authselect current | grep with-faillock" - failed_when: false - changed_when: false - check_mode: false - register: rhel8cis_5_4_2_profiles_faillock - - - name: "5.4.2 | AUDIT | Ensure authselect includes with-faillock| Show profiles" - ansible.builtin.debug: - msg: - - "Below are the current custom profiles" - - "{{ rhel8cis_5_4_2_profiles_faillock.stdout_lines }}" - - - name: "5.4.2 | PATCH | Ensure authselect includes with-faillock | Create custom profiles" - ansible.builtin.shell: "authselect select custom/{{ rhel8cis_authselect['custom_profile_name'] }} with-faillock without-nullok --force" - when: rhel8cis_authselect_custom_profile_select - - - name: 5.4.2 | PATCH | Ensure authselect includes with-faillock | not auth select profile" - ansible.builtin.lineinfile: - path: "/etc/pam.d/password-auth" - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - insertbefore: "{{ item.before }}" - loop: - - { 'regexp': '^auth\s+required\s+pam_faillock.so preauth silent deny=.*unlock_time=.*', 'line': 'auth required pam_faillock.so preauth', 'before':'^auth\s+sufficient\s+pam_unix.so try_first_pass'} - - { 'regexp': '^auth\s+required\s+pam_faillock.so authfail deny=.*unlock_time=.*', 'line': 'auth required pam_faillock.so authfail', 'before':'^auth\s+required\s+pam_deny.so'} - - { 'regexp': '^account\s+required\s+pam_faillock.so', 'line': 'account required pam_faillock.so', 'before':'^account required pam_unix.so'} - when: - - not rhel8cis_authselect_custom_profile_select - - rhel8cis_pamd_manual_risks == 'ACCEPT' - - ansible_distribution_version >= "8.2" - - - name: 5.4.2 | PATCH | Ensure authselect includes with-faillock | not auth select profile" - ansible.builtin.lineinfile: - path: "/etc/pam.d/system-auth" - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - insertbefore: "{{ item.before | default(omit)}}" - loop: - - { 'regexp': '^auth\s+required\s+pam_faillock.so preauth silent deny=.*unlock_time=.*', 'line':'auth required pam_faillock.so preauth silent', 'before':'^auth\s+sufficient\s+pam_unix.so try_first_pass'} - - { 'regexp': '^auth\s+required\s+pam_faillock.so authfail deny=.*unlock_time=.*', 'line': 'auth required pam_faillock.so authfail', 'before':'^auth\s+required\s+pam_deny.so'} - - { 'regexp': '^account\s+required\s+pam_faillock.so', 'line': 'account required pam_faillock.so', 'before':'^account required pam_unix.so'} - when: - - not rhel8cis_authselect_custom_profile_select - - rhel8cis_pamd_manual_risks == 'ACCEPT' - - ansible_distribution_version >= "8.2" - when: - - rhel8cis_rule_5_4_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - authselect - - rule_5.4.2 diff --git a/tasks/section_5/cis_5.5.x.yml b/tasks/section_5/cis_5.5.x.yml deleted file mode 100644 index 56f86e9d..00000000 --- a/tasks/section_5/cis_5.5.x.yml +++ /dev/null @@ -1,121 +0,0 @@ ---- - -- name: "5.5.1 | PATCH | Ensure password creation requirements are configured" - block: - - name: "5.5.1 | PATCH | Ensure password creation requirements are configured | Set pwquality config settings" - ansible.builtin.lineinfile: - path: /etc/security/pwquality.conf - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - with_items: - - { regexp: '^minlen', line: 'minlen = {{ rhel8cis_pam_password.minlen }}' } - - { regexp: '^minclass', line: 'minclass = {{ rhel8cis_pam_password.minclass }}' } - - - name: "5.5.1 | PATCH | Ensure password creation requirements are configured | Set system-auth and password-auth retry settings" - ansible.builtin.lineinfile: - path: "{{ item }}" - regexp: '^password\s*requisite\s*pam_pwquality.so' - line: "password requisite pam_pwquality.so try_first_pass local_users_only enforce_for_root retry=3" - insertbefore: '^#?password ?' - with_items: - - /etc/pam.d/system-auth - - /etc/pam.d/password-auth - when: - - rhel8cis_rule_5_5_1 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.5.1 - -- name: "5.5.2 | PATCH | Ensure system accounts are secured | pre RHEL8.2" - block: - - name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | pre RHEL8.2 | Add deny count and unlock time for preauth" - ansible.builtin.lineinfile: - path: /etc/pam.d/{{ item }} - state: present - regexp: '^auth\s*required\s*pam_faillock.so preauth' - line: "auth required pam_faillock.so preauth silent deny={{ rhel8cis_pam_faillock.attempts }}{{ (rhel8cis_pam_faillock.fail_for_root) | ternary(' even_deny_root ',' ') }}unlock_time={{ rhel8cis_pam_faillock.unlock_time }}" - insertafter: '^#?auth ?' - with_items: - - "system-auth" - - "password-auth" - when: ansible_distribution_version <= "8.1" - - - name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | pre RHEL8.2 | Add deny count and unlock times for authfail" - ansible.builtin.lineinfile: - dest: /etc/pam.d/{{ item }} - state: present - regexp: '^auth\s*required\s*pam_faillock.so authfail' - line: "auth required pam_faillock.so authfail deny={{ rhel8cis_pam_faillock.attempts }}{{ (rhel8cis_pam_faillock.fail_for_root) | ternary(' even_deny_root ',' ') }}unlock_time={{ rhel8cis_pam_faillock.unlock_time }}" - insertafter: '^#?auth ?' - with_items: - - "system-auth" - - "password-auth" - when: ansible_distribution_version <= "8.1" - - - name: "5.5.2 | PATCH | Ensure system accounts are secured | RHEL8.2+ " - ansible.builtin.lineinfile: - path: /etc/security/faillock.conf - state: present - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - with_items: - - { regexp: '^\s*deny\s*=\s*[1-5]\b', line: 'deny = 5' } - - { regexp: '^\s*unlock_time\s*=\s*(0|9[0-9][0-9]|[1-9][0-9][0-9][0-9]+)\b', line: 'unlock_time = 900' } - when: ansible_distribution_version >= "8.2" - when: - - rhel8cis_rule_5_5_2 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.5.2 - -# This is only setting the pam_pwhistory remember due to the man page for pam_unix.so saying you should not use the remember feature -# Man page entry below -# remember=n -# The last n passwords for each user are saved in /etc/security/opasswd in order to force password -# change history and keep the user from alternating between the same password too frequently. The MD5 -# password hash algorithm is used for storing the old passwords. Instead of this option the -# pam_pwhistory module should be used. -- name: "5.5.3 | PATCH | Ensure password reuse is limited" - ansible.builtin.lineinfile: - path: /etc/pam.d/system-auth - state: present - line: "password requisite pam_pwhistory.so try_first_pass local_users_only enforce_for_root retry=3 remember={{ rhel8cis_pam_faillock.remember }}" - insertafter: '^password\s*requisite\s*pam_pwquality.so' - when: - - rhel8cis_rule_5_5_3 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.5.3 - -- name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512" - block: - - name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | libuser.conf" - ansible.builtin.replace: - path: "{{ item.path }}" - regexp: "{{ item.regexp }}" - replace: "{{ item.replace }}" - with_items: - - { path: /etc/libuser.conf, regexp: '^crypt_style\s*=\s*.*$', replace: 'crypt_style = sha512' } - - { path: /etc/login.defs, regexp: '^ENCRYPT_METHOD.*', replace: 'ENCRYPT_METHOD SHA512' } - - - name: "5.5.4 | PATCH | Ensure password reuse is limited | pwhistory" - ansible.builtin.replace: - path: "{{ item }}" - regexp: '^password\s*sufficient\s*pam_unix.so.*$' - replace: 'password sufficient pam_unix.so sha512 shadow try_first_pass use_authtok remember={{ rhel8cis_pam_faillock.remember }}' - with_items: - - /etc/pam.d/password-auth - - /etc/pam.d/system-auth - when: - - rhel8cis_rule_5_5_4 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.5.4 diff --git a/tasks/section_5/cis_5.6.1.x.yml b/tasks/section_5/cis_5.6.1.x.yml deleted file mode 100644 index 2cc5abd2..00000000 --- a/tasks/section_5/cis_5.6.1.x.yml +++ /dev/null @@ -1,230 +0,0 @@ ---- - -- name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less" - block: - - name: "5.6.1.1 | AUDIT | Ensure password expiration is 365 days or less | Capture accounts more than 365" - ansible.builtin.shell: "grep -E '^[^:]+:[^!*]' /etc/shadow | awk -F':' '$5>{{ rhel8cis_pass['max_days'] }} { print $1 }'" - changed_when: false - failed_when: rhel8cis_5_6_1_1_pass_max_expire.rc not in [ 0, 1 ] - register: rhel8cis_5_6_1_1_pass_max_expire - - - name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less | update login.defs" - ansible.builtin.lineinfile: - path: /etc/login.defs - regexp: '^PASS_MAX_DAYS' - line: "PASS_MAX_DAYS {{ rhel8cis_pass['max_days'] }}" - - - name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less | Ensure all accounts set to 365" - ansible.builtin.user: - name: "{{ item }}" - password_expire_max: "{{ rhel8cis_pass['max_days'] }}" - loop: "{{ rhel8cis_5_6_1_1_pass_max_expire.stdout_lines | default([]) }}" - when: - - rhel8cis_5_6_1_1_set_max_expiry - - item not in rhel8cis_5_6_1_1_user_skip_list - - - name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less | Warning" - block: - - name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less | Output list if not set to change" - ansible.builtin.debug: - msg: | - "Warning!! The following account are set beyond the expected expiration date: - {{ rhel8cis_5_6_1_1_pass_max_expire.stdout_lines | default([]) }}" - - - name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less | set warning fact" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '5.6.1.1' - when: - - rhel8cis_5_6_1_1_pass_max_expire is defined - - rhel8cis_5_6_1_1_pass_max_expire.stdout | length > 0 - - not rhel8cis_5_6_1_1_set_max_expiry - when: - - rhel8cis_rule_5_6_1_1 - tags: - - level1-server - - level1-workstation - - automated - - patch - - password - - rule_5.6.1.1 - -- name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is 7 or more" - block: - - name: "5.6.1.2 | AUDIT | Ensure minimum days between password changes is 7 or more | Capture accounts 7 or more" - ansible.builtin.shell: "grep -E '^[^:]+:[^!*]' /etc/shadow | awk -F':' '$4>{{ rhel8cis_pass['min_days'] }} { print $1 }'" - changed_when: false - failed_when: rhel8cis_5_6_1_2_min_day_change.rc not in [ 0, 1 ] - register: rhel8cis_5_6_1_2_min_day_change - - - name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is 7 or more" - ansible.builtin.lineinfile: - path: /etc/login.defs - regexp: '^PASS_MIN_DAYS' - line: "PASS_MIN_DAYS {{ rhel8cis_pass['min_days'] }}" - - - name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is 7 or more | Change users found" - ansible.builtin.user: - name: "{{ item }}" - password_expire_min: "{{ rhel8cis_pass['min_days'] }}" - loop: "{{ rhel8cis_5_6_1_2_min_day_change.stdout_lines | default([]) }}" - when: - - rhel8cis_5_6_1_2_set_min_days_change - - - name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is 7 or more | Warning" - block: - - name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is 7 or more | Output list if not set to change" - ansible.builtin.debug: - msg: | - "Warning!! The following account are set beyond the expected minimum days between passwords: - {{ rhel8cis_5_6_1_2_min_day_change.stdout_lines }}" - - - name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is 7 or more | set warning fact" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '5.6.1.2' - when: - - rhel8cis_5_6_1_2_min_day_change is defined - - rhel8cis_5_6_1_2_min_day_change.stdout | length > 0 - - not rhel8cis_5_6_1_2_set_min_days_change - when: - - rhel8cis_rule_5_6_1_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - password - - rule_5.6.1.2 - -- name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more" - block: - - name: "5.6.1.3 | AUDIT | Ensure password expiration warning days is 7 or more | capture accounts" - ansible.builtin.shell: "grep -E '^[^:]+:[^!*]' /etc/shadow | awk -F':' '$4>{{ rhel8cis_pass['warn_age'] }} { print $1 }'" - changed_when: false - failed_when: rhel8cis_5_6_1_3_warn_age_change.rc not in [ 0, 1 ] - register: rhel8cis_5_6_1_3_warn_age_change - - - name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | set default" - ansible.builtin.lineinfile: - path: /etc/login.defs - regexp: '^PASS_WARN_AGE' - line: "PASS_WARN_AGE {{ rhel8cis_pass['warn_age'] }}" - - - name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | Change users found" - ansible.builtin.shell: "change --warndays {{ rhel8cis_pass['warn_age'] }} {{ item }}" - loop: "{{ rhel8cis_5_6_1_3_warn_age_change.stdout_lines | default([]) }}" - when: - - rhel8cis_5_6_1_3_set_warn_age_change - - - name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | warning" - block: - - name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | Output list if not set to change" - ansible.builtin.debug: - msg: | - "Warning!! The following account are set beyond the expected warning date: - {{ rhel8cis_5_6_1_3_warn_age_change.stdout_lines }}" - - - name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | set warning fact" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '5.6.1.3' - when: - - rhel8cis_5_6_1_3_warn_age_change is defined - - rhel8cis_5_6_1_3_warn_age_change.stdout | length > 0 - - not rhel8cis_5_6_1_3_set_warn_age_change - - when: - - rhel8cis_rule_5_6_1_3 - - tags: - - level1-server - - level1-workstation - - automated - - patch - - password - - rule_5.6.1.3 - -- name: "5.6.1.4 | PATCH | Ensure inactive password lock is 30 days or less" - block: - - name: "5.6.1.4 | AUDIT | Ensure inactive password lock is 30 days or less | Getting user list" - ansible.builtin.shell: "awk -F: '/^[^#:]+:[^\\!\\*:]*:[^:]*:[^:]*:[^:]*:[^:]*:(\\s*|-1|3[1-9]|[4-9][0-9]|[1-9][0-9][0-9]+):[^:]*:[^:]*\\s*$/ {print $1}' /etc/shadow" - changed_when: false - check_mode: false - register: rhel_8_5_6_1_4_user_list - - - name: "5.6.1.4 | AUDIT | Ensure inactive password lock is 30 days or less | Check current settings" - ansible.builtin.shell: useradd -D | grep INACTIVE={{ rhel8cis_inactivelock.lock_days }} | cut -f2 -d= - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_5_6_1_4_inactive_settings - - - name: "5.6.1.4 | PATCH | Ensure inactive password lock is 30 days or less | Set default inactive setting" - ansible.builtin.shell: useradd -D -f {{ rhel8cis_inactivelock.lock_days }} - when: rhel8cis_5_6_1_4_inactive_settings.stdout | length == 0 - - - name: "5.6.1.4 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts" - ansible.builtin.shell: "chage --inactive {{ rhel8cis_inactivelock.lock_days }} {{ item }}" - with_items: - - "{{ rhel_8_5_6_1_4_user_list.stdout_lines }}" - when: - - rhel8cis_rule_5_6_1_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - password - - rule_5.6.1.4 - -- name: "5.6.1.5 | PATCH | Ensure all users last password change date is in the past" - block: - - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Get current date in Unix Time" - ansible.builtin.shell: echo $(($(date --utc --date "$1" +%s)/86400)) - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_5_6_1_5_currentut - - - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Get list of users with last changed pw date in the future" - ansible.builtin.shell: "cat /etc/shadow | awk -F: '{if($3>{{ rhel8cis_5_6_1_5_currentut.stdout }})print$1}'" - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_5_6_1_5_user_list - - - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Alert no pw change in the future exist" - ansible.builtin.debug: - msg: "Good News! All accounts have PW change dates that are in the past" - when: rhel8cis_5_6_1_5_user_list.stdout | length == 0 - - - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Alert on accounts with pw change in the future" - ansible.builtin.debug: - msg: "Warning!! The following accounts have the last PW change date in the future: {{ rhel8cis_5_6_1_5_user_list.stdout_lines }}" - when: - - rhel8cis_5_6_1_5_user_list.stdout | length > 0 - - not rhel8cis_futurepwchgdate_autofix - - - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past| Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '5.6.1.5' - when: - - rhel8cis_5_6_1_5_user_list.stdout | length > 0 - - not rhel8cis_futurepwchgdate_autofix - - - name: "5.6.1.5 | PATCH | Ensure all users last password change date is in the past | Fix accounts with pw change in the future" - ansible.builtin.shell: passwd --expire {{ item }} - when: - - rhel8cis_5_6_1_5_user_list | length > 0 - - rhel8cis_futurepwchgdate_autofix - with_items: - - "{{ rhel8cis_5_6_1_5_user_list.stdout_lines }}" - when: - - rhel8cis_rule_5_6_1_5 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.6.1.5 diff --git a/tasks/section_5/cis_5.6.x.yml b/tasks/section_5/cis_5.6.x.yml deleted file mode 100644 index 9f73d59a..00000000 --- a/tasks/section_5/cis_5.6.x.yml +++ /dev/null @@ -1,118 +0,0 @@ ---- - -- name: "5.6.2 | PATCH | Ensure system accounts are secured" - block: - - name: "5.6.2 | Ensure system accounts are secured | Set nologin" - ansible.builtin.user: - name: "{{ item.id }}" - shell: /usr/sbin/nologin - with_items: - - "{{ rhel8cis_passwd }}" - when: - - item.id != "root" - - item.id != "sync" - - item.id != "shutdown" - - item.id != "halt" - - item.uid < rhel8uid_interactive_uid_start | int - - item.shell != "/bin/false" - - item.shell != "/usr/sbin/nologin" - loop_control: - label: "{{ item.id }}" - - - name: "5.6.2 | PATCH | Ensure system accounts are secured | Lock accounts" - ansible.builtin.user: - name: "{{ item.id }}" - password_lock: true - with_items: - - "{{ rhel8cis_passwd }}" - when: - - item.id != "halt" - - item.id != "shutdown" - - item.id != "sync" - - item.id != "root" - - item.id != "nfsnobody" - - item.uid < rhel8uid_interactive_uid_start | int - - item.shell != "/bin/false" - - item.shell != "/usr/sbin/nologin" - loop_control: - label: "{{ item.id }}" - when: - - rhel8cis_rule_5_6_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - accounts - - rule_5.6.2 - -- name: "5.6.3 | PATCH | Ensure default user shell timeout is 900 seconds or less" - ansible.builtin.blockinfile: - path: "{{ item.path }}" - state: "{{ item.state }}" - create: true - mode: 0644 - marker: "# {mark} ANSIBLE MANAGED" - block: | - # Set session timeout - CIS ID RHEL-08-5.6.3 - TMOUT={{ rhel8cis_shell_session_timeout.timeout }} - export TMOUT - readonly TMOUT - with_items: - - { path: "{{ rhel8cis_shell_session_timeout.file }}", state: present } - - { path: /etc/profile, state: "{{ (rhel8cis_shell_session_timeout.file == '/etc/profile') | ternary('present', 'absent') }}" } - when: - - rhel8cis_rule_5_6_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - accounts - - rule_5.6.3 - -- name: "5.6.4 | PATCH | Ensure default group for the root account is GID 0" - ansible.builtin.shell: usermod -g 0 root - changed_when: false - failed_when: false - when: - - rhel8cis_rule_5_6_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - accounts - - rule_5.6.4 - -- name: "5.6.5 | PATCH | Ensure default user umask is 027 or more restrictive" - block: - - name: "5.6.5 | PATCH | Ensure default user umask is 027 or more restrictive | Set umask for /etc/login.defs pam_umask settings" - ansible.builtin.replace: - path: /etc/login.defs - regexp: "{{ item.regexp }}" - replace: "{{ item.replace }}" - loop: - - { regexp: '(UMASK\s+)0[012][0-6]', replace: '\1 027' } - - { regexp: '(USERGROUPS_ENAB\s+)yes', replace: '\1 no' } - - - name: "5.6.5 | PATCH | Ensure default user umask is 027 or more restrictive | Set umask for /etc/bashrc" - ansible.builtin.replace: - path: /etc/bashrc - regexp: '(^\s+umask) 0[012][0-6]' - replace: '\1 027' - - - name: "5.6.5 | PATCH | Ensure default user umask is 027 or more restrictive | Set umask for /etc/profile" - ansible.builtin.replace: - path: /etc/profile - regexp: '(^\s+umask) 0[012][0-6]' - replace: '\1 027' - when: - - rhel8cis_rule_5_6_5 - tags: - - level1-server - - level1-workstation - - automated - - patch - - accounts - - rule_5.6.5 diff --git a/tasks/section_5/main.yml b/tasks/section_5/main.yml index 5aed1c18..74c518bf 100644 --- a/tasks/section_5/main.yml +++ b/tasks/section_5/main.yml @@ -1,26 +1,44 @@ --- -# Access, Authentication, and Authorization - -- name: "SECTION | 5.1 | Configure time-based job schedulers" - ansible.builtin.import_tasks: cis_5.1.x.yml - -- name: "SECTION | 5.2 | Configure SSH Server" - ansible.builtin.import_tasks: cis_5.2.x.yml +# 5.1 Configure Logging +- name: "SECTION | 5.1.1.x | Configure rsyslog" + ansible.builtin.import_tasks: + file: cis_5.1.1.x.yml + when: rhel8cis_syslog == 'rsyslog' + +- name: "SECTION | 5.1.2.x | Configure journald" + ansible.builtin.import_tasks: + file: cis_5.1.2.x.yml + +- name: "SECTION | 5.1.3 | Configure logile perms" + ansible.builtin.import_tasks: + file: cis_5.1.3.yml + +- name: "SECTION | 5.1.4 | Configure logrotate" + ansible.builtin.import_tasks: + file: cis_5.1.4.yml + +# 5.2 Configure System Accounting (auditd) +- name: "SECTION | 5.2.1 | Ensure auditing is enabled" + ansible.builtin.import_tasks: + file: cis_5.2.1.x.yml when: - - "'openssh-server' in ansible_facts.packages" + - not system_is_container -- name: "SECTION | 5.3 | Configure privilege escalation" - ansible.builtin.import_tasks: cis_5.3.x.yml - -- name: "SECTION | 5.4 | Configure authselect" - ansible.builtin.import_tasks: cis_5.4.x.yml +- name: "SECTION | 5.2.2 | Configure Data Retention" + ansible.builtin.import_tasks: + file: cis_5.2.2.x.yml + when: + - not system_is_container -- name: "SECTION | 5.5 | Configure PAM " - ansible.builtin.import_tasks: cis_5.5.x.yml +- name: "SECTION | 5.2.3.x | Configure auditd rules" + ansible.builtin.import_tasks: + file: cis_5.2.3.x.yml -- name: "SECTION | 5.6.1.x | Shadow Password Suite Parameters" - ansible.builtin.import_tasks: cis_5.6.1.x.yml +- name: "SECTION | 5.2.3.x | Audit file permissions" + ansible.builtin.import_tasks: + file: cis_5.2.3.x.yml -- name: "SECTION | 5.6.x | Misc. User Account Settings" - ansible.builtin.import_tasks: cis_5.6.x.yml +- name: "SECTION | 5.3.x | Aide" + ansible.builtin.import_tasks: + file: cis_5.3.x.yml diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index e05701cc..e33743d6 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -1,68 +1,42 @@ --- -- name: "6.1.1 | AUDIT | Audit system file permissions" - block: - - name: "6.1.1 | AUDIT | Audit system file permissions | Audit the packages" - ansible.builtin.shell: rpm -Va --nomtime --nosize --nomd5 --nolinkto - changed_when: false - failed_when: false - register: rhel8cis_6_1_1_packages_rpm - - - name: "6.1.1 | AUDIT | Audit system file permissions | Create list and warning" - block: - - name: "6.1.1 | AUDIT | Audit system file permissions | Add file discrepancy list to system" - ansible.builtin.copy: - dest: "{{ rhel8cis_rpm_audit_file }}" # noqa template-instead-of-copy - content: "{{ rhel8cis_6_1_1_packages_rpm.stdout }}" - owner: root - group: root - mode: 0644 - - - name: "6.1.1 | AUDIT | Audit system file permissions | Message out alert for package descrepancies" - ansible.builtin.debug: - msg: | - "Warning!! You have some package descrepancies issues. - The file list can be found in {{ rhel8cis_rpm_audit_file }}" - when: rhel8cis_6_1_1_packages_rpm.stdout|length > 0 - - - name: "6.1.1 | AUDIT | Audit system file permissions | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.1.1' - when: rhel8cis_6_1_1_packages_rpm.stdout | length > 0 - +- name: "6.1.1 | PATCH | Ensure permissions on /etc/passwd are configured" when: - rhel8cis_rule_6_1_1 tags: - - level2-server - - level2-workstation - - manual - - audit + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.1 + ansible.builtin.file: + path: /etc/passwd + owner: root + group: root + mode: u-x,go-wx -- name: "6.1.2 | PATCH | Ensure sticky bit is set on all world-writable directories" - ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -0002 2>/dev/null | xargs chmod a+t - changed_when: false - failed_when: false +- name: "6.1.2 | PATCH | Ensure permissions on /etc/passwd- are configured" when: - rhel8cis_rule_6_1_2 tags: - - skip_ansible_lint - level1-server - level1-workstation - automated - patch - - stickybits - - permissons + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - permissions - rule_6.1.2 - -- name: "6.1.3 | PATCH | Ensure permissions on /etc/passwd are configured" ansible.builtin.file: - path: /etc/passwd + path: /etc/passwd- owner: root group: root - mode: 0644 + mode: u-x,go-wx + +- name: "6.1.3 | PATCH | Ensure permissions on /etc/security/opasswd are configured" when: - rhel8cis_rule_6_1_3 tags: @@ -70,15 +44,17 @@ - level1-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.3 - -- name: "6.1.4 | PATCH | Ensure permissions on /etc/shadow are configured" ansible.builtin.file: - path: /etc/shadow + path: /etc/security/opasswd owner: root group: root - mode: 0000 + mode: '0600' + +- name: "6.1.4 | PATCH | Ensure permissions on /etc/group are configured" when: - rhel8cis_rule_6_1_4 tags: @@ -86,15 +62,17 @@ - level1-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.4 - -- name: "6.1.5 | PATCH | Ensure permissions on /etc/group are configured" ansible.builtin.file: path: /etc/group owner: root group: root - mode: 0644 + mode: u-x,go-wx + +- name: "6.1.5 | PATCH | Ensure permissions on /etc/group- are configured" when: - rhel8cis_rule_6_1_5 tags: @@ -102,15 +80,17 @@ - level1-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.5 - -- name: "6.1.6 | PATCH | Ensure permissions on /etc/gshadow are configured" ansible.builtin.file: - path: /etc/gshadow + path: /etc/group- owner: root group: root - mode: 0000 + mode: u-x,go-wx + +- name: "6.1.6 | PATCH | Ensure permissions on /etc/shadow are configured" when: - rhel8cis_rule_6_1_6 tags: @@ -118,15 +98,17 @@ - level1-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.6 - -- name: "6.1.7 | PATCH | Ensure permissions on /etc/passwd- are configured" ansible.builtin.file: - path: /etc/passwd- + path: /etc/shadow owner: root group: root - mode: 0644 + mode: '0000' + +- name: "6.1.7 | PATCH | Ensure permissions on /etc/shadow- are configured" when: - rhel8cis_rule_6_1_7 tags: @@ -134,15 +116,17 @@ - level1-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.7 - -- name: "6.1.8 | PATCH | Ensure permissions on /etc/shadow- are configured" ansible.builtin.file: path: /etc/shadow- owner: root group: root - mode: 0000 + mode: '0000' + +- name: "6.1.8 | PATCH | Ensure permissions on /etc/gshadow are configured" when: - rhel8cis_rule_6_1_8 tags: @@ -150,15 +134,17 @@ - level1-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.8 - -- name: "6.1.9 | PATCH | Ensure permissions on /etc/group- are configured" ansible.builtin.file: - path: /etc/group- + path: /etc/gshadow owner: root group: root - mode: 0644 + mode: '0000' + +- name: "6.1.9 | PATCH | Ensure permissions on /etc/gshadow- are configured" when: - rhel8cis_rule_6_1_9 tags: @@ -166,15 +152,17 @@ - level1-workstation - automated - patch - - permissionss + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - permissions - rule_6.1.9 - -- name: "6.1.10 | PATCH | Ensure permissions on /etc/gshadow- are configured" ansible.builtin.file: path: /etc/gshadow- owner: root group: root - mode: 0000 + mode: '0000' + +- name: "6.1.10 | PATCH | Ensure permissions on /etc/shells are configured" when: - rhel8cis_rule_6_1_10 tags: @@ -182,220 +170,260 @@ - level1-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.10 + ansible.builtin.file: + path: /etc/shells + owner: root + group: root + mode: u-x,go-wx -- name: "6.1.11 | PATCH | Ensure no world writable files exist" +- name: "6.1.11 | PATCH | Ensure world writable files and directories are secured" + when: + - rhel8cis_rule_6_1_11 + - rhel8cis_disruption_high + tags: + - level1-server + - level1-workstation + - automated + - patch + - files + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - permissions + - rule_6.1.11 + vars: + warn_control_id: '6.1.11' block: - - name: "6.1.11 | AUDIT | Ensure no world writable files exist | Get list of world-writable files" + - name: "6.1.11 | AUDIT | Ensure world writable files and directories are secured | Get list of world-writable files" ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -0002 failed_when: false changed_when: false register: rhel_08_6_1_11_perms_results - - name: "6.1.11 | PATCH | Ensure no world writable files exist | Adjust world-writable files if they exist (Configurable)" + - name: "6.1.11 | PATCH | Adjust world-writable files if they exist (Configurable)" + when: + - rhel_08_6_1_11_perms_results.stdout_lines is defined + - rhel8cis_no_world_write_adjust ansible.builtin.file: path: '{{ item }}' mode: o-w state: touch with_items: "{{ rhel_08_6_1_11_perms_results.stdout_lines }}" + + - name: "6.1.11 | PATCH | Ensure world writable files and directories are secured | sticky bit set on world-writable directories" + ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -0002 2>/dev/null | xargs chmod a+t + changed_when: false + failed_when: false + + - name: "6.1.11 | AUDIT | Ensure world writable files and directories are secured | Warning" when: - rhel_08_6_1_11_perms_results.stdout_lines is defined - - rhel8cis_no_world_write_adjust + - not rhel8cis_no_world_write_adjust + ansible.builtin.debug: + msg: "Warning!! - WorldWritable files have been found" - - name: "6.1.11 | AUDIT | Ensure no world writable files exist | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.1.11' + - name: "6.1.11 | AUDIT | Ensure world writable files and directories are secured | Warn Count" when: - rhel_08_6_1_11_perms_results.stdout_lines is defined - not rhel8cis_no_world_write_adjust + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "6.1.12 | PATCH | Ensure no ungrouped files or directories exist" when: - - rhel8cis_rule_6_1_11 + - rhel8cis_rule_6_1_12 + - rhel8cis_disruption_high tags: - level1-server - level1-workstation - automated - patch - - files + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_6.1.12 - permissions - - rule_6.1.11 - -- name: "6.1.12 | AUDIT | Ensure no unowned files or directories exist" + vars: + warn_control_id: '6.1.12' block: - - name: "6.1.12 | AUDIT | Ensure no unowned files or directories exist | Finding all unowned files or directories" - ansible.builtin.shell: find "{{ item.mount }}" -xdev -nouser + - name: "6.1.12 | AUDIT | Ensure no ungrouped files or directories exist | Get ungrouped files or directories" + ansible.builtin.shell: find {{ item.mount }} -xdev -nogroup -not -fstype nfs changed_when: false failed_when: false check_mode: false - register: rhel_08_6_1_12_audit - with_items: "{{ ansible_mounts }}" + register: rhel8cis_6_1_12_ungrouped_items + with_items: + - "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.mount }}" - when: - - item['device'].startswith('/dev') - - not 'bind' in item['options'] - - name: "6.1.12 | AUDIT | Ensure no unowned files or directories exist | set fact" + - name: "6.1.12 | AUDIT | Ensure no ungrouped files or directories exist | Flatten ungrouped_items results for easier use" ansible.builtin.set_fact: - rhel_08_6_1_12_unowned_files_found: true - loop: "{{ rhel_08_6_1_12_audit.results }}" - when: - - item | length > 0 - - item.stdout is defined # skipped items are part of results list, but don't have the registered module properties - - item.stdout | length > 0 + rhel8cis_6_1_12_ungrouped_items_flatten: "{{ rhel8cis_6_1_12_ungrouped_items.results | map(attribute='stdout_lines') | flatten }}" - - name: "6.1.12 | AUDIT | Ensure no unowned files or directories exist | Displaying any unowned files or directories" - ansible.builtin.debug: - msg: "Warning -- missing owner on items in {{ rhel_08_6_1_12_audit | json_query('results[*].stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] + - name: "6.1.12 | AUDIT | Ensure no ungrouped files or directories exist | Alert on ungrouped files and directories" when: - - rhel_08_6_1_12_unowned_files_found - - - name: "6.1.12 | AUDIT | Ensure no unowned files or directories exist | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.1.12' - when: rhel_08_6_1_12_unowned_files_found - vars: - rhel_08_6_1_12_unowned_files_found: false - when: - - rhel8cis_rule_6_1_12 - tags: - - level1-server - - level1-workstation - - automated - - audit - - files - - permissions - - rule_6.1.12 + - not rhel8cis_ungrouped_adjust + - rhel8cis_6_1_12_ungrouped_items_flatten | length > 0 + ansible.builtin.debug: + msg: + - "Warning!! You have ungrouped files/directories and are configured to not auto-remediate for this task" + - "Please review the files/directories below and assign a group" + - "{{ rhel8cis_6_1_12_ungrouped_items_flatten }}" -- name: "6.1.13 | AUDIT | Ensure no ungrouped files or directories exist" - block: - - name: "6.1.13 | AUDIT | Ensure no ungrouped files or directories exist | Finding all ungrouped files or directories" - ansible.builtin.shell: find "{{ item.mount }}" -xdev -nogroup - check_mode: false - failed_when: false - changed_when: false - register: rhel_08_6_1_13_audit - with_items: "{{ ansible_mounts }}" - loop_control: - label: "{{ item.mount }}" + - name: "6.1.12 | PATCH | Ensure no ungrouped files or directories exist | Set ungrouped files/directories to configured group" when: - - item['device'].startswith('/dev') - - not 'bind' in item['options'] + - rhel8cis_ungrouped_adjust + - rhel8cis_6_1_12_ungrouped_items_flatten | length > 0 + ansible.builtin.file: + path: "{{ item }}" + group: "{{ rhel8cis_ungrouped_group }}" + loop: + - "{{ rhel8cis_6_1_12_ungrouped_items_flatten }}" - - name: "6.1.13 | AUDIT | Ensure no ungrouped files or directories exist | set fact" - ansible.builtin.set_fact: - rhel_08_6_1_13_ungrouped_files_found: true - loop: "{{ rhel_08_6_1_13_audit.results }}" + - name: "6.1.12 | AUDIT | Ensure no ungrouped files or directories exist | Warn Count" when: - - item | length > 0 - - item.stdout is defined # skipped items are part of results list, but don't have the registered module properties - - item.stdout | length > 0 + - rhel8cis_ungrouped_adjust + - rhel8cis_6_1_12_ungrouped_items_flatten | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml - - name: "6.1.13 | AUDIT | Ensure no ungrouped files or directories exist | Displaying all ungrouped files or directories" - ansible.builtin.debug: - msg: "Warning!! -- Missing group on items in {{ rhel_08_6_1_13_audit | json_query('results[*].stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] - when: rhel_08_6_1_13_ungrouped_files_found - - - name: "6.1.13 | AUDIT | Ensure no ungrouped files or directories exist | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.1.13' - when: rhel_08_6_1_13_ungrouped_files_found - vars: - rhel_08_6_1_13_ungrouped_files_found: false +- name: "6.1.13 | AUDIT | Ensure SUID and SGID files are reviewed" when: - rhel8cis_rule_6_1_13 + - rhel8cis_disruption_high tags: - level1-server - level1-workstation - - automated + - manual - audit - - files - - permissions - rule_6.1.13 - -- name: "6.1.14 | AUDIT | Audit SUID executables" + - permissions + vars: + warn_control_id: '6.1.13' block: - - name: "6.1.14 | AUDIT | Audit SUID executables | Find all SUID executables" - ansible.builtin.shell: df {{ item.mount }} -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -4000 + - name: "6.1.13 | AUDIT | Ensure SUID and SGID files are reviewed | Find SUID executables" + ansible.builtin.shell: find {{ item.mount }} -xdev -type f -perm -4000 -not -fstype nfs + changed_when: false failed_when: false + check_mode: false + register: rhel8cis_6_1_13_suid_executables + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.mount }}" + + - name: "6.1.13 | AUDIT | Ensure SUID and SGID files are reviewed | Find all SGID executables" + ansible.builtin.shell: find {{ item.mount }} -xdev -type f -perm -2000 -not -fstype nfs changed_when: false - register: rhel_08_6_1_14_suid_perms - with_items: "{{ ansible_mounts }}" + failed_when: false + check_mode: false + register: rhel8cis_6_1_13_sgid_executables + loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.mount }}" - - name: "6.1.14 | AUDIT | Audit SUID executables | set fact SUID executables" + - name: "6.1.13 | AUDIT | Ensure SUID and SGID files are reviewed | Flatten suid_executables results for easier use" ansible.builtin.set_fact: - rhel8cis_6_1_14_suid_found: true - loop: "{{ rhel_08_6_1_14_suid_perms.results }}" + rhel8cis_6_1_13_suid_executables_flatten: "{{ rhel8cis_6_1_13_suid_executables.results | map(attribute='stdout_lines') | flatten }}" + + - name: "6.1.13 | AUDIT | Ensure SUID and SGID files are reviewed | Set fact SGID executables" + ansible.builtin.set_fact: + rhel8cis_6_1_13_sgid_executables_flatten: "{{ rhel8cis_6_1_13_sgid_executables.results | map(attribute='stdout_lines') | flatten }}" + + - name: "6.1.13 | PATCH | Ensure SUID and SGID files are reviewed | Remove SUID bit" + when: + - rhel8cis_suid_adjust + - rhel8cis_6_1_13_suid_executables_flatten | length > 0 + ansible.builtin.file: + path: "{{ item }}" + mode: 'u-s' + loop: + - "{{ rhel8cis_6_1_13_suid_executables_flatten }}" + + - name: "6.1.13 | PATCH | Audit SGID executables | Remove SGID bit" + ansible.builtin.file: + path: "{{ item }}" + mode: 'g-s' + with_items: + - "{{ rhel8cis_6_1_13_sgid_executables_flatten }}" when: - - item | length > 0 - - item.stdout is defined # skipped items are part of results list, but don't have the registered module properties - - item.stdout | length > 0 + - rhel8cis_sgid_adjust + - rhel8cis_6_1_13_sgid_executables_flatten | length > 0 - - name: "6.1.14 | AUDIT | Audit SUID executables | Alert SUID executables exist" + - name: "6.1.13 | WARN | Ensure SUID and SGID files are reviewed | Alert SUID executables exist" + when: + - rhel8cis_6_1_13_suid_executables_flatten | length > 0 + - not rhel8cis_suid_adjust ansible.builtin.debug: - msg: "Warning!! -- SUID set on items in {{ rhel_08_6_1_14_suid_perms | json_query('results[*].stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] - when: rhel8cis_6_1_14_suid_found - - - name: "6.1.14 | AUDIT | Audit SUID executables | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.1.14' - when: rhel8cis_6_1_14_suid_found - vars: - rhel8cis_6_1_14_suid_found: false + msg: + - "Warning!! You have SUID executables" + - "The files are listed below, please confirm the integrity of these binaries" + - "{{ rhel8cis_6_1_13_suid_executables_flatten }}" + + - name: "6.1.13 | WARN | Ensure SUID and SGID files are reviewed | Alert SGID executables exist" + when: + - rhel8cis_6_1_13_sgid_executables_flatten | length > 0 + - not rhel8cis_sgid_adjust + ansible.builtin.debug: + msg: + - "Warning!! You have SGID executables" + - "The files are listed below, please review the integrity of these binaries" + - "{{ rhel8cis_6_1_13_sgid_executables_flatten }}" + + - name: "6.1.13 | WARN | Ensure SUID and SGID files are reviewed | Warn Count" + when: + - (rhel8cis_6_1_13_suid_executables_flatten | length > 0 and not rhel8cis_suid_adjust) or + (rhel8cis_6_1_13_sgid_executables_flatten | length > 0 and not rhel8cis_sgid_adjust) + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "6.1.14 | AUDIT | Audit system file permissions" when: - rhel8cis_rule_6_1_14 + - rhel8cis_disruption_high tags: - - level1-server - - level1-workstation + - level2-server + - level2-workstation - manual - audit - - files + - NIST800-53R5_AC-3 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - NIST800-53R5_MP-2 + - permissions - rule_6.1.14 - -- name: "6.1.15 | AUDIT | Audit SGID executables" + vars: + warn_control_id: '6.1.14' block: - - name: "6.1.15 | AUDIT | Audit SGID executables | Find all SGID executables" - ansible.builtin.shell: df {{ item.mount }} -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -2000 - failed_when: false + - name: "6.1.14 | AUDIT | Audit system file permissions | Audit the packages" + ansible.builtin.shell: rpm -Va --nomtime --nosize --nomd5 --nolinkto changed_when: false - register: rhel_08_6_1_15_sgid_perms - loop: "{{ ansible_mounts }}" - loop_control: - label: "{{ item.mount }}" + failed_when: false + register: rhel8cis_6_1_14_packages_rpm - - name: "6.1.15 | AUDIT | Audit SGID executables | Set fact SGID executables" - ansible.builtin.set_fact: - rhel8cis_6_1_15_sgid_found: true - loop: "{{ rhel_08_6_1_15_sgid_perms.results }}" - when: - - item | length > 0 - - item.stdout is defined # skipped items are part of results list, but don't have the registered module properties - - item.stdout | length > 0 + - name: "6.1.14 | AUDIT | Audit system file permissions | Create list and warning" + block: + - name: "6.1.14 | AUDIT | Audit system file permissions | Add file discrepancy list to system" + ansible.builtin.copy: + dest: "{{ rhel8cis_rpm_audit_file }}" # noqa template-instead-of-copy + content: "{{ rhel8cis_6_1_14_packages_rpm.stdout }}" + owner: root + group: root + mode: '0644' - - name: "6.1.15 | AUDIT | Audit SGID executables | Alert SGID executables exist" - ansible.builtin.debug: - msg: "Warning!! -- SGID set on items in {{ rhel_08_6_1_15_sgid_perms | json_query('results[*].stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] - when: rhel8cis_6_1_15_sgid_found - - - name: "6.1.15 | AUDIT | Audit SGID executables | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.1.15' - when: rhel8cis_6_1_15_sgid_found - vars: - rhel8cis_6_1_15_guid_found: false - when: - - rhel8cis_rule_6_1_15 - tags: - - level1-server - - level1-workstation - - manual - - audit - - files - - rule_6.1.15 + - name: "6.1.14 | AUDIT | Audit system file permissions | Message out alert for package descrepancies" + when: rhel8cis_6_1_14_packages_rpm.stdout | length > 0 + ansible.builtin.debug: + msg: | + "Warning!! You have some package descrepancies issues. + The file list can be found in {{ rhel8cis_rpm_audit_file }}" + + - name: "6.1.14 | AUDIT | Audit system file permissions | Warn Count" + when: rhel8cis_6_1_14_packages_rpm.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml diff --git a/tasks/section_6/cis_6.2.x.yml b/tasks/section_6/cis_6.2.x.yml index 94dbe775..311bc49e 100644 --- a/tasks/section_6/cis_6.2.x.yml +++ b/tasks/section_6/cis_6.2.x.yml @@ -1,69 +1,65 @@ --- -- name: "6.2.1 | PATCH | Ensure password fields are not empty" - ansible.builtin.shell: passwd -l {{ item }} - changed_when: false - failed_when: false - with_items: "{{ empty_password_accounts.stdout_lines }}" +- name: "6.2.1 | AUDIT | Ensure accounts in /etc/passwd use shadowed passwords" when: - - empty_password_accounts.stdout is defined - rhel8cis_rule_6_2_1 tags: - level1-server - level1-workstation - automated - - patch - - accounts + - audit + - NIST800-53R5_IA-5 - rule_6.2.1 - -- name: "6.2.2 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group" + - user_accounts + vars: + warn_control_id: '6.2.1' block: - - name: "6.2.2 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Check /etc/passwd entries" - ansible.builtin.shell: pwck -r | grep 'no group' | awk '{ gsub("[:\47]",""); print $2}' + - name: "6.2.1 | AUDIT | Ensure accounts in /etc/passwd use shadowed passwords | Get users not using shadowed passwords" + ansible.builtin.shell: awk -F':' '($2 != "x" ) { print $1}' /etc/passwd changed_when: false failed_when: false - check_mode: false - register: rhel8cis_6_2_2_passwd_gid_check + register: rhel8cis_6_2_1_nonshadowed_users - - name: "6.2.2 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Print warning about users with invalid GIDs missing GID entries in /etc/group" + - name: "6.2.1 | AUDIT | Ensure accounts in /etc/passwd use shadowed passwords | Warn on findings" + when: rhel8cis_6_2_1_nonshadowed_users.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following users have non-existent GIDs (Groups): {{ rhel8cis_6_2_2_passwd_gid_check.stdout_lines | join (', ') }}" - when: rhel8cis_6_2_2_passwd_gid_check.stdout | length > 0 - - - name: "6.2.2 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.2.2' - when: rhel8cis_6_2_2_passwd_gid_check.stdout | length > 0 + msg: + - "Warning!! You have users that are not using a shadowed password. Please convert the below accounts to use a shadowed password" + - "{{ rhel8cis_6_2_1_nonshadowed_users.stdout_lines }}" + + - name: "6.2.1 | WARN | Ensure accounts in /etc/passwd use shadowed passwords | warn_count" + when: rhel8cis_6_2_1_nonshadowed_users.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "6.2.2 | PATCH | Ensure /etc/shadow password fields are not empty" when: - rhel8cis_rule_6_2_2 tags: - level1-server - level1-workstation - automated - - audit - - accounts - - groups + - patch - rule_6.2.2 - -- name: "6.2.3 | AUDIT | Ensure no duplicate UIDs exist" + - NIST800-53R5_IA-5 + - user + - permissions block: - - name: "6.2.3 | AUDIT | Ensure no duplicate UIDs exist | Check for duplicate UIDs" - ansible.builtin.shell: "pwck -r | awk -F: '{if ($3 in uid) print $1 ; else uid[$3]}' /etc/passwd" + - name: "6.2.2 | AUDIT | Ensure /etc/shadow password fields are not empty | Find users with no password" + ansible.builtin.shell: awk -F":" '($2 == "" ) { print $1 }' /etc/shadow changed_when: false - failed_when: false - register: rhel8cis_6_2_3_user_uid_check + check_mode: false + register: rhel8cis_6_2_2_empty_password_acct - - name: "6.2.3 | AUDIT | Ensure no duplicate UIDs exist | Print warning about users with duplicate UIDs" - ansible.builtin.debug: - msg: "Warning!! The following users have UIDs that are duplicates: {{ rhel8cis_6_2_3_user_uid_check.stdout_lines }}" - when: rhel8cis_6_2_3_user_uid_check.stdout | length > 0 - - - name: "6.2.3 | AUDIT | Ensure no duplicate UIDs exist | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.2.3' - when: rhel8cis_6_2_3_user_uid_check.stdout | length > 0 + - name: "6.2.2 | PATCH | Ensure /etc/shadow password fields are not empty | Lock users with empty password" + when: rhel8cis_6_2_2_empty_password_acct.stdout | length > 0 + ansible.builtin.user: + name: "{{ item }}" + password_lock: true + loop: + - "{{ rhel8cis_6_2_2_empty_password_acct.stdout_lines }}" + +- name: "6.2.3 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group" when: - rhel8cis_rule_6_2_3 tags: @@ -71,29 +67,34 @@ - level1-workstation - automated - audit - - accounts - - users - rule_6.2.3 - -- name: "6.2.4 | AUDIT | Ensure no duplicate GIDs exist" + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - groups + vars: + warn_control_id: '6.2.3' block: - - name: "6.2.4 | AUDIT | Ensure no duplicate GIDs exist | Check for duplicate GIDs" - ansible.builtin.shell: "pwck -r | awk -F: '{if ($3 in users) print $1 ; else users[$3]}' /etc/group" + - name: "6.2.3 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Check /etc/passwd entries" + ansible.builtin.shell: pwck -r | grep 'no group' | awk '{ gsub("[:\47]",""); print $2}' changed_when: false failed_when: false - register: rhel8cis_6_2_4_user_user_check + check_mode: false + register: rhel8cis_6_2_3_passwd_gid_check - - name: "6.2.4 | AUDIT | Ensure no duplicate GIDs exist | Print warning about users with duplicate GIDs" + - name: "6.2.3 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Print warning about users with invalid GIDs missing GID entries in /etc/group" + when: rhel8cis_6_2_3_passwd_gid_check.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following groups have duplicate GIDs: {{ rhel8cis_6_2_4_user_user_check.stdout_lines }}" - when: rhel8cis_6_2_4_user_user_check.stdout | length > 0 + msg: "Warning!! The following users have non-existent GIDs (Groups): {{ rhel8cis_6_2_3_passwd_gid_check.stdout_lines | join (', ') }}" - - name: "6.2.4 | AUDIT | Ensure no duplicate GIDs exist | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.2.4' - when: rhel8cis_6_2_4_user_user_check.stdout | length > 0 + - name: "6.2.3 | WARN | Ensure all groups in /etc/passwd exist in /etc/group | warn_count" + when: rhel8cis_6_2_3_passwd_gid_check.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml +- name: "6.2.4 | AUDIT | Ensure no duplicate UIDs exist" when: - rhel8cis_rule_6_2_4 tags: @@ -101,28 +102,34 @@ - level1-workstation - automated - audit - - accounts - - groups + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_6.2.4 - -- name: "6.2.5 | AUDIT | Ensure no duplicate user names exist" + - user + vars: + warn_control_id: '6.2.4' block: - - name: "6.2.5 | AUDIT | Ensure no duplicate user names exist | Check for duplicate User Names" - ansible.builtin.shell: "pwck -r | awk -F: '{if ($1 in users) print $1 ; else users[$1]}' /etc/passwd" + - name: "6.2.4 | AUDIT | Ensure no duplicate UIDs exist | Check for duplicate UIDs" + ansible.builtin.shell: "pwck -r | awk -F: '{if ($3 in uid) print $1 ; else uid[$3]}' /etc/passwd" changed_when: false failed_when: false - register: rhel8cis_6_2_5_user_username_check + check_mode: false + register: rhel8cis_6_2_4_user_uid_check - - name: "6.2.5 | AUDIT | Ensure no duplicate user names exist | Print warning about users with duplicate User Names" + - name: "6.2.4 | AUDIT | Ensure no duplicate UIDs exist | Print warning about users with duplicate UIDs" + when: rhel8cis_6_2_4_user_uid_check.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following user names are duplicates: {{ rhel8cis_6_2_5_user_username_check.stdout_lines }}" - when: rhel8cis_6_2_5_user_username_check.stdout | length > 0 - - - name: "6.2.5 | AUDIT | Ensure no duplicate user names exist | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.2.5' - when: rhel8cis_6_2_5_user_username_check.stdout | length > 0 + msg: "Warning!! The following users have UIDs that are duplicates: {{ rhel8cis_6_2_4_user_uid_check.stdout_lines }}" + + - name: "6.2.4 | AUDIT | Ensure no duplicate UIDs exist | Set warning count" + when: rhel8cis_6_2_4_user_uid_check.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "6.2.5 | AUDIT | Ensure no duplicate GIDs exist" when: - rhel8cis_rule_6_2_5 tags: @@ -130,29 +137,36 @@ - level1-workstation - automated - audit - - accounts - - users + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_6.2.5 - -- name: "6.2.6 | AUDIT | Ensure no duplicate group names exist" + - groups + vars: + warn_control_id: '6.2.5' block: - - name: "6.2.6 | AUDIT | Ensure no duplicate group names exist | Check for duplicate group names" - ansible.builtin.shell: 'getent passwd | cut -d: -f1 | sort -n | uniq -d' + - name: "6.2.5 | AUDIT | Ensure no duplicate GIDs exist | Check for duplicate GIDs" + ansible.builtin.shell: "pwck -r | awk -F: '{if ($3 in users) print $1 ; else users[$3]}' /etc/group" changed_when: false failed_when: false check_mode: false - register: rhel8cis_6_2_6_group_group_check + register: rhel8cis_6_2_5_user_user_check - - name: "6.2.6 | AUDIT | Ensure no duplicate group names exist | Print warning about users with duplicate group names" + - name: "6.2.5 | AUDIT | Ensure no duplicate GIDs exist | Print warning about users with duplicate GIDs" + when: rhel8cis_6_2_5_user_user_check.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following group names are duplicates: {{ rhel8cis_6_2_6_group_group_check.stdout_lines }}" - when: rhel8cis_6_2_6_group_group_check.stdout | length > 0 - - - name: "6.2.6 | AUDIT | Ensure no duplicate group names exist | Warn count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.2.6' - when: rhel8cis_6_2_6_group_group_check.stdout | length > 0 + msg: "Warning!! The following groups have duplicate GIDs: {{ rhel8cis_6_2_5_user_user_check.stdout_lines }}" + + - name: "6.2.5 | AUDIT | Ensure no duplicate GIDs exist | Set warning count" + when: rhel8cis_6_2_5_user_user_check.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "6.2.6 | AUDIT | Ensure no duplicate user names exist" + vars: + warn_control_id: '6.2.6' when: - rhel8cis_rule_6_2_6 tags: @@ -160,321 +174,280 @@ - level1-workstation - automated - audit - - accounts - - groups - rule_6.2.6 - -- name: "6.2.7 | PATCH | Ensure root PATH Integrity" + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - user block: - - name: "6.2.7 | AUDIT | Ensure root PATH Integrity | Determine empty value" - ansible.builtin.shell: 'echo $PATH | grep ::' - changed_when: false - failed_when: rhel8cis_6_2_7_path_colon.rc == 0 - check_mode: false - register: rhel8cis_6_2_7_path_colon - - - name: "6.2.7 | AUDIT | Ensure root PATH Integrity | Determin colon end" - ansible.builtin.shell: 'echo $PATH | grep :$' - changed_when: false - failed_when: rhel8cis_6_2_7_path_colon_end.rc == 0 - check_mode: false - register: rhel8cis_6_2_7_path_colon_end - - - name: "6.2.7 | AUDIT | Ensure root PATH Integrity | Determine dot in path" - ansible.builtin.shell: "/bin/bash --login -c 'env | grep ^PATH=' | sed -e 's/PATH=//' -e 's/::/:/' -e 's/:$//' -e 's/:/\\n/g'" + - name: "6.2.6 | AUDIT | Ensure no duplicate user names exist | Check for duplicate User Names" + ansible.builtin.shell: "pwck -r | awk -F: '{if ($1 in users) print $1 ; else users[$1]}' /etc/passwd" changed_when: false - failed_when: '"." in rhel8cis_6_2_7_dot_in_path.stdout_lines' + failed_when: false check_mode: false - register: rhel8cis_6_2_7_dot_in_path + register: rhel8cis_6_2_6_username_check - - name: "6.2.7 | AUDIT | Ensure root PATH Integrity | Alert on empty value, colon end, and dot in path" + - name: "6.2.6 | WARN | Ensure no duplicate user names exist | Print warning about users with duplicate User Names" + when: rhel8cis_6_2_6_username_check.stdout | length > 0 ansible.builtin.debug: - msg: - - "The following paths have an empty value: {{ rhel8cis_6_2_7_path_colon.stdout_lines }}" - - "The following paths have colon end: {{ rhel8cis_6_2_7_path_colon_end.stdout_lines }}" - - "The following paths have a dot in the path: {{ rhel8cis_6_2_7_dot_in_path.stdout_lines }}" + msg: "Warning!! The following user names are duplicates: {{ rhel8cis_6_2_6_user_username_check.stdout_lines }}" - - name: "6.2.7 | PATCH | Ensure root PATH Integrity | Determine rights and owner" - ansible.builtin.file: - path: '{{ item }}' - follow: true - state: directory - owner: root - mode: 'o-w,g-w' - with_items: "{{ rhel8cis_6_2_7_dot_in_path.stdout_lines }}" + - name: "6.2.6 | WARN | Ensure no duplicate user names exist | Set warning count" + when: rhel8cis_6_2_6_username_check.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "6.2.7 | AUDIT | Ensure no duplicate group names exist" when: - rhel8cis_rule_6_2_7 tags: - level1-server - level1-workstation - automated - - patch - - paths + - audit + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_6.2.7 + - groups + vars: + warn_control_id: '6.2.7' + block: + - name: "6.2.7 | AUDIT | Ensure no duplicate group names exist | Check for duplicate group names" + ansible.builtin.shell: 'getent passwd | cut -d: -f1 | sort -n | uniq -d' + changed_when: false + failed_when: false + check_mode: false + register: rhel8cis_6_2_7_group_check -- name: "6.2.8 | PATCH | Ensure root is the only UID 0 account" - ansible.builtin.shell: passwd -l {{ item }} - changed_when: false - failed_when: false - with_items: "{{ rhel8cis_uid_zero_accounts_except_root.stdout_lines }}" + - name: "6.2.7 | AUDIT | Ensure no duplicate group names exist | Print warning about users with duplicate group names" + when: rhel8cis_6_2_7_group_check.stdout | length > 0 + ansible.builtin.debug: + msg: "Warning!! The following group names are duplicates: {{ rhel8cis_6_2_7_group_group_check.stdout_lines }}" + + - name: "6.2.7 | AUDIT | Ensure no duplicate group names exist | Set warning count" + when: rhel8cis_6_2_7_group_check.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "6.2.8 | PATCH | Ensure root PATH Integrity" when: - - rhel8cis_uid_zero_accounts_except_root.stdout is defined - rhel8cis_rule_6_2_8 tags: - level1-server - level1-workstation - - automated - patch - - accounts - - users + - paths + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_6.2.8 - -- name: "6.2.9 | PATCH | Ensure all users' home directories exist" block: - - name: "6.2.9 | AUDIT | Ensure all users' home directories exist" - ansible.builtin.stat: - path: "{{ item }}" - register: rhel_08_6_2_9_audit - with_items: "{{ rhel8cis_passwd | selectattr('shell', '!=', '/bin/false') | selectattr('shell', '!=', '/usr/bin/nologin') | selectattr('uid', '>=', rhel8uid_interactive_uid_start | int ) | selectattr('uid', '<=', rhel8uid_interactive_uid_stop | int ) | map(attribute='dir') | list }}" + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Get root paths" + ansible.builtin.shell: sudo -Hiu root env | grep '^PATH' | cut -d= -f2 + changed_when: false + register: rhel8cis_6_2_8_root_paths - - name: "6.2.9 | AUDIT | Ensure all users' home directories exist" - ansible.builtin.shell: find -H {{ item.0 | quote }} -type d -not -type l -perm /027 - check_mode: false - changed_when: rhel_08_6_2_9_patch_audit.stdout | length > 0 - register: rhel_08_6_2_9_patch_audit - when: - - ansible_check_mode - - item.1.exists - with_together: - - "{{ rhel_08_6_2_9_audit.results | map(attribute='item') | list }}" - - "{{ rhel_08_6_2_9_audit.results | map(attribute='stat') | list }}" - loop_control: - label: "{{ item.0 }}" + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Get root paths" + ansible.builtin.shell: sudo -Hiu root env | grep '^PATH' | cut -d= -f2 | tr ":" "\n" + changed_when: false + register: rhel8cis_6_2_8_root_paths_split - - name: "6.2.9 | PATCH | Ensure all users' home directories exist" - ansible.builtin.file: - path: "{{ item.0 }}" - recurse: false - mode: a-st,g-w,o-rwx - register: rhel_08_6_2_9_patch - when: - - not ansible_check_mode - - item.1.exists - with_together: - - "{{ rhel_08_6_2_9_audit.results | map(attribute='item') | list }}" - - "{{ rhel_08_6_2_9_audit.results | map(attribute='stat') | list }}" - loop_control: - label: "{{ item.0 }}" + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Set fact" + ansible.builtin.set_fact: + root_paths: "{{ rhel8cis_6_2_8_root_paths.stdout }}" - # set default ACLs so the homedir has an effective umask of 0027 - - name: "6.2.9 | PATCH | Ensure all users' home directories exist" - ansible.posix.acl: - path: "{{ item.0 }}" - default: true - state: present - recursive: true - follow: "{{ rhel_08_6_2_9_follow_home_symlinks }}" - etype: "{{ item.1.etype }}" - permissions: "{{ item.1.mode }}" - when: - - not system_is_container - with_nested: - - "{{ (ansible_check_mode | ternary(rhel_08_6_2_9_patch_audit, rhel_08_6_2_9_patch)).results | - rejectattr('skipped', 'defined') | map(attribute='item') | map('first') | list }}" - - - - etype: group - mode: rx - - etype: other - mode: '0' + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Check for empty dirs" + ansible.builtin.shell: 'echo {{ root_paths }} | grep -q "::" && echo "roots path contains a empty directory (::)"' + changed_when: false + failed_when: root_path_empty_dir.rc not in [ 0, 1 ] + register: root_path_empty_dir + + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Check for trailing ':'" + ansible.builtin.shell: '{{ root_paths }} | cut -d= -f2 | grep -q ":$" && echo "roots path contains a trailing (:)"' + changed_when: false + failed_when: root_path_trailing_colon.rc not in [ 0, 1 ] + register: root_path_trailing_colon + + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Check for owner and permissions" + block: + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Check for owner and permissions" + ansible.builtin.stat: + path: "{{ item }}" + register: root_path_perms + loop: "{{ rhel8cis_6_2_8_root_paths_split.stdout_lines }}" + + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Set permissions" + when: + - item.stat.exists + - item.stat.isdir + - item.stat.pw_name != 'root' or item.stat.gr_name != 'root' or item.stat.woth or item.stat.wgrp + - (item != 'root') and (not rhel8cis_uses_root) + ansible.builtin.file: + path: "{{ item.stat.path }}" + state: directory + owner: root + group: root + mode: '0755' + follow: false + loop: "{{ root_path_perms.results }}" + loop_control: + label: "{{ item }}" + +- name: "6.2.9 | PATCH | Ensure root is the only UID 0 account" when: + - rhel8cis_uid_zero_accounts_except_root.rc - rhel8cis_rule_6_2_9 tags: - level1-server - level1-workstation - - automated - patch + - accounts - users + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_6.2.9 + ansible.builtin.shell: passwd -l {{ item }} + changed_when: false + failed_when: false + loop: "{{ rhel8cis_uid_zero_accounts_except_root.stdout_lines }}" -- name: "6.2.10 | PATCH | Ensure users own their home directories" - ansible.builtin.file: - path: "{{ item.dir }}" - owner: "{{ item.id }}" - state: directory - with_items: "{{ rhel8cis_passwd }}" - loop_control: - label: "{{ rhel8cis_passwd_label }}" +- name: "6.2.10 | PATCH | Ensure local interactive user home directories exist" when: - - item.uid >= rhel8uid_interactive_uid_start|int - - item.id != 'nobody' - - item.dir != '/dev/null' - rhel8cis_rule_6_2_10 tags: - - skip_ansible_lint # settings found on 6_2_7 - level1-server - level1-workstation - - automated - patch - users + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_6.2.10 - -- name: "6.2.11 | PATCH | Ensure users' home directories permissions are 750 or more restrictive" block: - - name: "6.2.11 | AUDIT | Ensure users' home directories permissions are 750 or more restrictive" + - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Create dir if absent" + ansible.builtin.file: + path: "{{ item.dir }}" + state: directory + owner: "{{ item.id }}" + group: "{{ item.gid }}" + register: rhel8cis_6_2_10_home_dir + loop: "{{ rhel8cis_passwd | selectattr('uid', '>=', rhel8cis_min_uid.stdout | int ) | selectattr('uid', '<=', rhel8cis_max_uid.stdout | int ) | list }}" + loop_control: + label: "{{ item.id }}" + + - name: "6.2.10 | AUDIT | Ensure local interactive user home directories exist | Get perms stat" ansible.builtin.stat: path: "{{ item }}" - with_items: "{{ rhel8cis_passwd | selectattr('shell', '!=', '/bin/false') | selectattr('shell', '!=', '/usr/bin/nologin') | selectattr('uid', '>=', rhel8uid_interactive_uid_start | int) | selectattr('uid', '<=', rhel8uid_interactive_uid_stop | int) | map(attribute='dir') | list }}" - register: rhel_08_6_2_11_audit + register: rhel_09_6_2_10_home_dir_perms + loop: "{{ interactive_users_home.stdout_lines }}" - - name: "6.2.11 | AUDIT | Ensure users' home directories permissions are 750 or more restrictive" - ansible.builtin.shell: find -H {{ item.0 | quote }} type -d -not -type l -perm /027 - check_mode: false - changed_when: rhel_08_6_2_11_patch_audit.stdout | length > 0 - register: rhel_08_6_2_11_patch_audit - when: - - ansible_check_mode - - item.1.exists - with_together: - - "{{ rhel_08_6_2_11_audit.results | map(attribute='item') | list }}" - - "{{ rhel_08_6_2_11_audit.results | map(attribute='stat') | list }}" + - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Set perms if needed" + ansible.builtin.file: + path: "{{ item.stat.path }}" + state: directory + mode: g-w,o-rwx + loop: "{{ rhel_09_6_2_10_home_dir_perms.results }}" loop_control: - label: "{{ item.0 }}" + label: "{{ item }}" - - name: "6.2.11 | PATCH | Ensure users' home directories permissions are 750 or more restrictive" - ansible.builtin.file: - path: "{{ item.0 }}" - recurse: true - mode: a-st,g-w,o-rwx - follow: false - register: rhel_08_6_2_11_patch + - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Own their home directories" when: - - not ansible_check_mode - - item.1.exists - with_together: - - "{{ rhel_08_6_2_11_audit.results | map(attribute='item') | list }}" - - "{{ rhel_08_6_2_11_audit.results | map(attribute='stat') | list }}" + - item.uid >= rhel8cis_min_uid | int + - item.id != 'nobody' + - (item.id != 'tss' and item.dir != '/dev/null') + - item.shell != '/sbin/nologin' + - "'bin/nologin' not in item.shell" + - "'bin/false' not in item.shell" + ansible.builtin.file: + path: "{{ item.dir }}" + owner: "{{ item.id }}" + state: directory + loop: "{{ rhel8cis_passwd | selectattr('uid', '>=', rhel8cis_min_uid.stdout | int ) | selectattr('uid', '<=', rhel8cis_max_uid.stdout | int ) | list }}" loop_control: - label: "{{ item.0 }}" + label: "{{ item.id }}" # set default ACLs so the homedir has an effective umask of 0027 - - name: "6.2.11 | PATCH | Ensure users' home directories permissions are 750 or more restrictive" + - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Set group ACL" ansible.posix.acl: - path: "{{ item.0 }}" + path: "{{ item }}" default: true + etype: group + permissions: rx state: present - recursive: true - etype: "{{ item.1.etype }}" - permissions: "{{ item.1.mode }}" - when: - - not system_is_container - with_nested: - - "{{ (ansible_check_mode | ternary(rhel_08_6_2_11_patch_audit, rhel_08_6_2_11_patch)).results | - rejectattr('skipped', 'defined') | map(attribute='item') | map('first') | list }}" - - - - etype: group - mode: rx - - etype: other - mode: '0' + loop: "{{ interactive_users_home.stdout_lines }}" + when: not system_is_container + + - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Set other ACL" + ansible.posix.acl: + path: "{{ item }}" + default: true + etype: other + permissions: 0 + state: present + loop: "{{ interactive_users_home.stdout_lines }}" + when: not system_is_container + +- name: "6.2.11 | PATCH | Ensure local interactive user dot files access is configured" when: - rhel8cis_rule_6_2_11 + - rhel8cis_disruption_high tags: - level1-server - level1-workstation - automated - patch - - users - - permissions + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_6.2.11 - -- name: "6.2.12 | PATCH | Ensure users' dot files are not group or world-writable" + - user + vars: + warn_control_id: '6.2.11' block: - - name: "6.2.12 | AUDIT | Ensure users' dot files are not group or world-writable | Check for files" - ansible.builtin.shell: find /home/ -maxdepth 2 -name "\.*" -perm /g+w,o+w + - name: "6.2.11 | AUDIT | Ensure local interactive user dot files access is configured | Check for files" + ansible.builtin.shell: find /home/ -name "\.*" -perm /g+w,o+w changed_when: false - failed_when: false - register: rhel8cis_6_2_12_audit + failed_when: rhel8cis_6_2_11_audit.rc not in [ 0, 1 ] + check_mode: false + register: rhel8cis_6_2_11_audit - - name: "6.2.12 | PATCH | Ensure users' dot files are not group or world-writable | Changes files if configured" - ansible.builtin.file: - path: '{{ item }}' - mode: go-w - with_items: "{{ rhel8cis_6_2_12_audit.stdout_lines }}" + - name: "6.2.11 | AUDIT | Ensure local interactive user dot files access is configured | Warning on files found" when: - - rhel8cis_6_2_12_audit.stdout is defined + - rhel8cis_6_2_11_audit.stdout | length > 0 - rhel8cis_dotperm_ansiblemanaged - when: - - rhel8cis_rule_6_2_12 - tags: - - level1-server - - level1-workstation - - automated - - patch - - users - - permissions - - rule_6.2.12 -- name: "6.2.13 | PATCH | Ensure users' .netrc Files are not group or world accessible" - ansible.builtin.shell: /bin/true - changed_when: false - failed_when: false - when: - - rhel8cis_rule_6_2_13 - tags: - - level1-server - - level1-workstation - - automated - - patch - - users - - permissions - - notimplemented - - rule_6.2.13 - -- name: "6.2.14 | PATCH | Ensure no users have .forward files" - ansible.builtin.file: - path: "~{{ item }}/.forward" - state: absent - with_items: - - "{{ users.stdout_lines }}" - when: - - rhel8cis_rule_6_2_14 - tags: - - level1-server - - level1-workstation - - automated - - patch - - users - - files - - rule_6.2.14 - -- name: "6.2.15 | PATCH | Ensure no users have .netrc files" - ansible.builtin.file: - path: "~{{ item }}/.netrc" - state: absent - with_items: - - "{{ users.stdout_lines }}" - when: - - rhel8cis_rule_6_2_15 - tags: - - level1-server - - level1-workstation - - automated - - patch - - users - - files - - rule_6.2.15 - -- name: "6.2.16 | PATCH | Ensure no users have .rhosts files" - ansible.builtin.file: - path: "~{{ item }}/.rhosts" - state: absent - with_items: "{{ users.stdout_lines }}" - when: - - rhel8cis_rule_6_2_16 - tags: - - level1-server - - level1-workstation - - automated - - patch - - users - - files - - rule_6.2.16 + ansible.builtin.debug: + msg: + - "Warning!! You have group or world-writable dot files on your system and have configured for manual intervention" + + - name: "6.2.11 | PATCH | Ensure local interactive user dot files access is configured | Set warning count" + when: + - rhel8cis_6_2_11_audit.stdout | length > 0 + - rhel8cis_dotperm_ansiblemanaged + + ansible.builtin.import_tasks: + file: warning_facts.yml + + - name: "6.2.11 | PATCH | Ensure local interactive user dot files access is configured | Changes files if configured" + when: + - rhel8cis_6_2_11_audit.stdout | length > 0 + - rhel8cis_dotperm_ansiblemanaged + + ansible.builtin.file: + path: '{{ item }}' + mode: go-w + with_items: "{{ rhel8cis_6_2_11_audit.stdout_lines }}" diff --git a/tasks/section_6/main.yml b/tasks/section_6/main.yml index 35328e5f..b194fdc8 100644 --- a/tasks/section_6/main.yml +++ b/tasks/section_6/main.yml @@ -1,7 +1,9 @@ --- - name: "SECTION | 6.1 | System File Permissions" - ansible.builtin.import_tasks: cis_6.1.x.yml + ansible.builtin.import_tasks: + file: cis_6.1.x.yml - name: "SECTION | 6.2 | User and Group Settings" - ansible.builtin.import_tasks: cis_6.2.x.yml + ansible.builtin.import_tasks: + file: cis_6.2.x.yml diff --git a/tasks/warning_facts.yml b/tasks/warning_facts.yml index 6e804873..3032b7cb 100644 --- a/tasks/warning_facts.yml +++ b/tasks/warning_facts.yml @@ -14,7 +14,7 @@ # # warn_count the main variable for the number of warnings and each time a warn_control_id is added # the count increases by a value of 1 -- name: "{{ warn_control_id }} | AUDIT | Set fact for manual task warning." +- name: "{{ warn_control_id }} | WARNING | Set fact for manual task warning." ansible.builtin.set_fact: warn_control_list: "{{ warn_control_list }} [{{ warn_control_id }}]" warn_count: "{{ warn_count | int + 1 }}" diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index d86b83d3..fd5a4821 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -1,8 +1,5 @@ ## metadata for Audit benchmark -benchmark_version: '2.0.0' - -# Set if pre version 8.2 -is_pre82_release: {% if ansible_distribution_version >= "8.2" %}false{% else %}true{% endif %} +benchmark_version: '3.0.0' # Set if genuine RHEL (subscription manager check) not for derivatives e.g. CentOS host_os_distribution: {{ ansible_distribution }} @@ -10,9 +7,6 @@ host_os_distribution: {{ ansible_distribution }} # timeout for each command to run where set - default = 10seconds/10000ms timeout_ms: {{ audit_cmd_timeout }} -# Allow the audit to run heavy tests which may utilise resources and impact performance -run_heavy_tests: {{ audit_run_heavy_tests }} - # Taken from LE rhel8-cis rhel8cis_section1: {{ rhel8cis_section1 }} rhel8cis_section2: {{ rhel8cis_section2 }} @@ -27,7 +21,8 @@ rhel8cis_level_2: {{ rhel8cis_level_2 }} rhel8cis_selinux_disable: {{ rhel8cis_selinux_disable }} # to enable rules that may have IO impact on a system e.g. full filesystem scans or CPU heavy -run_heavy_tests: true +run_heavy_tests: {{ audit_run_heavy_tests }} + {% if rhel8cis_legacy_boot is defined %} rhel8cis_legacy_boot: {{ rhel8cis_legacy_boot }} {% endif %} @@ -40,62 +35,85 @@ rhel8cis_legacy_boot: {{ rhel8cis_legacy_boot }} rhel8cis_rule_1_1_1_1: {{ rhel8cis_rule_1_1_1_1 }} rhel8cis_rule_1_1_1_2: {{ rhel8cis_rule_1_1_1_2 }} rhel8cis_rule_1_1_1_3: {{ rhel8cis_rule_1_1_1_3 }} -rhel8cis_rule_1_1_2_1: {{ rhel8cis_rule_1_1_2_1 }} -rhel8cis_rule_1_1_2_2: {{ rhel8cis_rule_1_1_2_2 }} -rhel8cis_rule_1_1_2_3: {{ rhel8cis_rule_1_1_2_3 }} -rhel8cis_rule_1_1_2_4: {{ rhel8cis_rule_1_1_2_4 }} -rhel8cis_rule_1_1_3_1: {{ rhel8cis_rule_1_1_3_1 }} -rhel8cis_rule_1_1_3_2: {{ rhel8cis_rule_1_1_3_2 }} -rhel8cis_rule_1_1_3_3: {{ rhel8cis_rule_1_1_3_3 }} -rhel8cis_rule_1_1_3_4: {{ rhel8cis_rule_1_1_3_4 }} -rhel8cis_rule_1_1_4_1: {{ rhel8cis_rule_1_1_4_1 }} -rhel8cis_rule_1_1_4_2: {{ rhel8cis_rule_1_1_4_2 }} -rhel8cis_rule_1_1_4_3: {{ rhel8cis_rule_1_1_4_3 }} -rhel8cis_rule_1_1_4_4: {{ rhel8cis_rule_1_1_4_4 }} -rhel8cis_rule_1_1_5_1: {{ rhel8cis_rule_1_1_5_1 }} -rhel8cis_rule_1_1_5_2: {{ rhel8cis_rule_1_1_5_2 }} -rhel8cis_rule_1_1_5_3: {{ rhel8cis_rule_1_1_5_3 }} -rhel8cis_rule_1_1_5_4: {{ rhel8cis_rule_1_1_5_4 }} -rhel8cis_rule_1_1_6_1: {{ rhel8cis_rule_1_1_6_1 }} -rhel8cis_rule_1_1_6_2: {{ rhel8cis_rule_1_1_6_2 }} -rhel8cis_rule_1_1_6_3: {{ rhel8cis_rule_1_1_6_3 }} -rhel8cis_rule_1_1_6_4: {{ rhel8cis_rule_1_1_6_4 }} -rhel8cis_rule_1_1_7_1: {{ rhel8cis_rule_1_1_7_1 }} -rhel8cis_rule_1_1_7_2: {{ rhel8cis_rule_1_1_7_2 }} -rhel8cis_rule_1_1_7_3: {{ rhel8cis_rule_1_1_7_3 }} -rhel8cis_rule_1_1_7_4: {{ rhel8cis_rule_1_1_7_4 }} -rhel8cis_rule_1_1_7_5: {{ rhel8cis_rule_1_1_7_5 }} -rhel8cis_rule_1_1_8_1: {{ rhel8cis_rule_1_1_8_1 }} -rhel8cis_rule_1_1_8_2: {{ rhel8cis_rule_1_1_8_2 }} -rhel8cis_rule_1_1_8_3: {{ rhel8cis_rule_1_1_8_3 }} -rhel8cis_rule_1_1_9: {{ rhel8cis_rule_1_1_9 }} -rhel8cis_rule_1_1_10: {{ rhel8cis_rule_1_1_10 }} - -rhel8cis_rule_1_2_1: {% if ansible_distribution == "RedHat" and rhel8cis_rule_1_2_1 %}True{% else %}False{% endif %} # Only run if Redhat and Subscribed +rhel8cis_rule_1_1_1_4: {{ rhel8cis_rule_1_1_1_4 }} +rhel8cis_rule_1_1_1_5: {{ rhel8cis_rule_1_1_1_5 }} +rhel8cis_rule_1_1_1_6: {{ rhel8cis_rule_1_1_1_6 }} +rhel8cis_rule_1_1_1_7: {{ rhel8cis_rule_1_1_1_7 }} +rhel8cis_rule_1_1_1_8: {{ rhel8cis_rule_1_1_1_8 }} +# /tmp +rhel8cis_rule_1_1_2_1_1: {{ rhel8cis_rule_1_1_2_1_1 }} +rhel8cis_rule_1_1_2_1_2: {{ rhel8cis_rule_1_1_2_1_2 }} +rhel8cis_rule_1_1_2_1_3: {{ rhel8cis_rule_1_1_2_1_3 }} +rhel8cis_rule_1_1_2_1_4: {{ rhel8cis_rule_1_1_2_1_4 }} + +# /dev/shm +rhel8cis_rule_1_1_2_2_1: {{ rhel8cis_rule_1_1_2_2_1 }} +rhel8cis_rule_1_1_2_2_2: {{ rhel8cis_rule_1_1_2_2_2 }} +rhel8cis_rule_1_1_2_2_3: {{ rhel8cis_rule_1_1_2_2_3 }} +rhel8cis_rule_1_1_2_2_4: {{ rhel8cis_rule_1_1_2_2_4 }} + +# /home +rhel8cis_rule_1_1_2_3_1: {{ rhel8cis_rule_1_1_2_3_1 }} +rhel8cis_rule_1_1_2_3_2: {{ rhel8cis_rule_1_1_2_3_2 }} +rhel8cis_rule_1_1_2_3_3: {{ rhel8cis_rule_1_1_2_3_3 }} + +# /var +rhel8cis_rule_1_1_2_4_1: {{ rhel8cis_rule_1_1_2_4_1 }} +rhel8cis_rule_1_1_2_4_2: {{ rhel8cis_rule_1_1_2_4_2 }} +rhel8cis_rule_1_1_2_4_3: {{ rhel8cis_rule_1_1_2_4_3 }} + +# /var/tmp +rhel8cis_rule_1_1_2_5_1: {{ rhel8cis_rule_1_1_2_5_1 }} +rhel8cis_rule_1_1_2_5_2: {{ rhel8cis_rule_1_1_2_5_2 }} +rhel8cis_rule_1_1_2_5_3: {{ rhel8cis_rule_1_1_2_5_3 }} +rhel8cis_rule_1_1_2_5_4: {{ rhel8cis_rule_1_1_2_5_4 }} + +# /var/log +rhel8cis_rule_1_1_2_6_1: {{ rhel8cis_rule_1_1_2_6_1 }} +rhel8cis_rule_1_1_2_6_2: {{ rhel8cis_rule_1_1_2_6_2 }} +rhel8cis_rule_1_1_2_6_3: {{ rhel8cis_rule_1_1_2_6_3 }} +rhel8cis_rule_1_1_2_6_4: {{ rhel8cis_rule_1_1_2_6_4 }} + +# /var/log/audit +rhel8cis_rule_1_1_2_7_1: {{ rhel8cis_rule_1_1_2_7_1 }} +rhel8cis_rule_1_1_2_7_2: {{ rhel8cis_rule_1_1_2_7_2 }} +rhel8cis_rule_1_1_2_7_3: {{ rhel8cis_rule_1_1_2_7_3 }} +rhel8cis_rule_1_1_2_7_4: {{ rhel8cis_rule_1_1_2_7_4 }} + +# DNF - Patching +rhel8cis_rule_1_2_1: {{ rhel8cis_rule_1_2_1 }} rhel8cis_rule_1_2_2: {{ rhel8cis_rule_1_2_2 }} rhel8cis_rule_1_2_3: {{ rhel8cis_rule_1_2_3 }} rhel8cis_rule_1_2_4: {{ rhel8cis_rule_1_2_4 }} +rhel8cis_rule_1_2_5: {{ rhel8cis_rule_1_2_5 }} +# bootloader grub rhel8cis_rule_1_3_1: {{ rhel8cis_rule_1_3_1 }} rhel8cis_rule_1_3_2: {{ rhel8cis_rule_1_3_2 }} +# kernel sysctl and coredumps rhel8cis_rule_1_4_1: {{ rhel8cis_rule_1_4_1 }} rhel8cis_rule_1_4_2: {{ rhel8cis_rule_1_4_2 }} rhel8cis_rule_1_4_3: {{ rhel8cis_rule_1_4_3 }} - -rhel8cis_rule_1_5_1: {{ rhel8cis_rule_1_5_1 }} -rhel8cis_rule_1_5_2: {{ rhel8cis_rule_1_5_2 }} -rhel8cis_rule_1_5_3: {{ rhel8cis_rule_1_5_3 }} - -rhel8cis_rule_1_6_1_1: {{ rhel8cis_rule_1_6_1_1 }} -rhel8cis_rule_1_6_1_2: {{ rhel8cis_rule_1_6_1_2 }} -rhel8cis_rule_1_6_1_3: {{ rhel8cis_rule_1_6_1_3 }} -rhel8cis_rule_1_6_1_4: {{ rhel8cis_rule_1_6_1_4 }} -rhel8cis_rule_1_6_1_5: {{ rhel8cis_rule_1_6_1_5 }} -rhel8cis_rule_1_6_1_6: {{ rhel8cis_rule_1_6_1_6 }} -rhel8cis_rule_1_6_1_7: {{ rhel8cis_rule_1_6_1_7 }} -rhel8cis_rule_1_6_1_8: {{ rhel8cis_rule_1_6_1_8 }} - +rhel8cis_rule_1_4_4: {{ rhel8cis_rule_1_4_4 }} + +# SElinux +rhel8cis_rule_1_5_1_1: {{ rhel8cis_rule_1_5_1_1 }} +rhel8cis_rule_1_5_1_2: {{ rhel8cis_rule_1_5_1_2 }} +rhel8cis_rule_1_5_1_3: {{ rhel8cis_rule_1_5_1_3 }} +rhel8cis_rule_1_5_1_4: {{ rhel8cis_rule_1_5_1_4 }} +rhel8cis_rule_1_5_1_5: {{ rhel8cis_rule_1_5_1_5 }} +rhel8cis_rule_1_5_1_6: {{ rhel8cis_rule_1_5_1_6 }} +rhel8cis_rule_1_5_1_7: {{ rhel8cis_rule_1_5_1_7 }} +rhel8cis_rule_1_5_1_8: {{ rhel8cis_rule_1_5_1_8 }} + +# Crypto Policies +rhel8cis_rule_1_6_1: {{ rhel8cis_rule_1_6_1 }} +rhel8cis_rule_1_6_2: {{ rhel8cis_rule_1_6_2 }} +rhel8cis_rule_1_6_3: {{ rhel8cis_rule_1_6_3 }} +rhel8cis_rule_1_6_4: {{ rhel8cis_rule_1_6_4 }} + +# MOTD and messages rhel8cis_rule_1_7_1: {{ rhel8cis_rule_1_7_1 }} rhel8cis_rule_1_7_2: {{ rhel8cis_rule_1_7_2 }} rhel8cis_rule_1_7_3: {{ rhel8cis_rule_1_7_3 }} @@ -103,19 +121,25 @@ rhel8cis_rule_1_7_4: {{ rhel8cis_rule_1_7_4 }} rhel8cis_rule_1_7_5: {{ rhel8cis_rule_1_7_5 }} rhel8cis_rule_1_7_6: {{ rhel8cis_rule_1_7_6 }} +# Gnome desktop rhel8cis_rule_1_8_1: {{ rhel8cis_rule_1_8_1 }} rhel8cis_rule_1_8_2: {{ rhel8cis_rule_1_8_2 }} rhel8cis_rule_1_8_3: {{ rhel8cis_rule_1_8_3 }} rhel8cis_rule_1_8_4: {{ rhel8cis_rule_1_8_4 }} rhel8cis_rule_1_8_5: {{ rhel8cis_rule_1_8_5 }} - -rhel8cis_rule_1_9: {{ rhel8cis_rule_1_9 }} -rhel8cis_rule_1_10: {{ rhel8cis_rule_1_10 }} - -# section 2 rules +rhel8cis_rule_1_8_6: {{ rhel8cis_rule_1_8_6 }} +rhel8cis_rule_1_8_7: {{ rhel8cis_rule_1_8_7 }} +rhel8cis_rule_1_8_8: {{ rhel8cis_rule_1_8_8 }} +rhel8cis_rule_1_8_9: {{ rhel8cis_rule_1_8_9 }} +rhel8cis_rule_1_8_10: {{ rhel8cis_rule_1_8_10 }} + +# Section 2 rules +# time sync rhel8cis_rule_2_1_1: {{ rhel8cis_rule_2_1_1 }} rhel8cis_rule_2_1_2: {{ rhel8cis_rule_2_1_2 }} +rhel8cis_rule_2_1_3: {{ rhel8cis_rule_2_1_3 }} +# Server services rhel8cis_rule_2_2_1: {{ rhel8cis_rule_2_2_1 }} rhel8cis_rule_2_2_2: {{ rhel8cis_rule_2_2_2 }} rhel8cis_rule_2_2_3: {{ rhel8cis_rule_2_2_3 }} @@ -136,25 +160,29 @@ rhel8cis_rule_2_2_17: {{ rhel8cis_rule_2_2_17 }} rhel8cis_rule_2_2_18: {{ rhel8cis_rule_2_2_18 }} rhel8cis_rule_2_2_19: {{ rhel8cis_rule_2_2_19 }} rhel8cis_rule_2_2_20: {{ rhel8cis_rule_2_2_20 }} +rhel8cis_rule_2_2_21: {{ rhel8cis_rule_2_2_21 }} +rhel8cis_rule_2_2_22: {{ rhel8cis_rule_2_2_22 }} +# Client services rhel8cis_rule_2_3_1: {{ rhel8cis_rule_2_3_1 }} rhel8cis_rule_2_3_2: {{ rhel8cis_rule_2_3_2 }} rhel8cis_rule_2_3_3: {{ rhel8cis_rule_2_3_3 }} rhel8cis_rule_2_3_4: {{ rhel8cis_rule_2_3_4 }} rhel8cis_rule_2_3_5: {{ rhel8cis_rule_2_3_5 }} -rhel8cis_rule_2_3_6: {{ rhel8cis_rule_2_3_6 }} - -rhel8cis_rule_2_4: {{ rhel8cis_rule_2_4 }} # Section 3 rules +# network connectivity wifi/bluetooth/ipv6 rhel8cis_rule_3_1_1: {{ rhel8cis_rule_3_1_1 }} rhel8cis_rule_3_1_2: {{ rhel8cis_rule_3_1_2 }} rhel8cis_rule_3_1_3: {{ rhel8cis_rule_3_1_3 }} -rhel8cis_rule_3_1_4: {{ rhel8cis_rule_3_1_4 }} +# Network Kernel module rhel8cis_rule_3_2_1: {{ rhel8cis_rule_3_2_1 }} rhel8cis_rule_3_2_2: {{ rhel8cis_rule_3_2_2 }} +rhel8cis_rule_3_2_3: {{ rhel8cis_rule_3_2_3 }} +rhel8cis_rule_3_2_4: {{ rhel8cis_rule_3_2_4 }} +# Network Kernel Params rhel8cis_rule_3_3_1: {{ rhel8cis_rule_3_3_1 }} rhel8cis_rule_3_3_2: {{ rhel8cis_rule_3_3_2 }} rhel8cis_rule_3_3_3: {{ rhel8cis_rule_3_3_3 }} @@ -164,161 +192,206 @@ rhel8cis_rule_3_3_6: {{ rhel8cis_rule_3_3_6 }} rhel8cis_rule_3_3_7: {{ rhel8cis_rule_3_3_7 }} rhel8cis_rule_3_3_8: {{ rhel8cis_rule_3_3_8 }} rhel8cis_rule_3_3_9: {{ rhel8cis_rule_3_3_9 }} +rhel8cis_rule_3_3_10: {{ rhel8cis_rule_3_3_10 }} +rhel8cis_rule_3_3_11: {{ rhel8cis_rule_3_3_11 }} +# Firewall rhel8cis_rule_3_4_1_1: {{ rhel8cis_rule_3_4_1_1 }} rhel8cis_rule_3_4_1_2: {{ rhel8cis_rule_3_4_1_2 }} -rhel8cis_rule_3_4_1_3: {{ rhel8cis_rule_3_4_1_3 }} -rhel8cis_rule_3_4_1_4: {{ rhel8cis_rule_3_4_1_4 }} -rhel8cis_rule_3_4_1_5: {{ rhel8cis_rule_3_4_1_5 }} -rhel8cis_rule_3_4_1_6: {{ rhel8cis_rule_3_4_1_6 }} -rhel8cis_rule_3_4_1_7: {{ rhel8cis_rule_3_4_1_7 }} +# Firewall rules rhel8cis_rule_3_4_2_1: {{ rhel8cis_rule_3_4_2_1 }} rhel8cis_rule_3_4_2_2: {{ rhel8cis_rule_3_4_2_2 }} rhel8cis_rule_3_4_2_3: {{ rhel8cis_rule_3_4_2_3 }} rhel8cis_rule_3_4_2_4: {{ rhel8cis_rule_3_4_2_4 }} rhel8cis_rule_3_4_2_5: {{ rhel8cis_rule_3_4_2_5 }} -rhel8cis_rule_3_4_2_6: {{ rhel8cis_rule_3_4_2_6 }} -rhel8cis_rule_3_4_2_7: {{ rhel8cis_rule_3_4_2_7 }} -rhel8cis_rule_3_4_2_8: {{ rhel8cis_rule_3_4_2_8 }} -rhel8cis_rule_3_4_2_9: {{ rhel8cis_rule_3_4_2_9 }} -rhel8cis_rule_3_4_2_10: {{ rhel8cis_rule_3_4_2_10 }} -rhel8cis_rule_3_4_2_11: {{ rhel8cis_rule_3_4_2_11 }} - -rhel8cis_rule_3_4_3_1_1: {{ rhel8cis_rule_3_4_3_1_1 }} -rhel8cis_rule_3_4_3_1_2: {{ rhel8cis_rule_3_4_3_1_2 }} -rhel8cis_rule_3_4_3_1_3: {{ rhel8cis_rule_3_4_3_1_3 }} - -rhel8cis_rule_3_4_3_2_1: {{ rhel8cis_rule_3_4_3_2_1 }} -rhel8cis_rule_3_4_3_2_2: {{ rhel8cis_rule_3_4_3_2_2 }} -rhel8cis_rule_3_4_3_2_3: {{ rhel8cis_rule_3_4_3_2_3 }} -rhel8cis_rule_3_4_3_2_4: {{ rhel8cis_rule_3_4_3_2_4 }} -rhel8cis_rule_3_4_3_2_5: {{ rhel8cis_rule_3_4_3_2_5 }} -rhel8cis_rule_3_4_3_2_6: {{ rhel8cis_rule_3_4_3_2_6 }} - -rhel8cis_rule_3_4_3_3_1: {{ rhel8cis_rule_3_4_3_3_1 }} -rhel8cis_rule_3_4_3_3_2: {{ rhel8cis_rule_3_4_3_3_2 }} -rhel8cis_rule_3_4_3_3_3: {{ rhel8cis_rule_3_4_3_3_3 }} -rhel8cis_rule_3_4_3_3_4: {{ rhel8cis_rule_3_4_3_3_4 }} -rhel8cis_rule_3_4_3_3_5: {{ rhel8cis_rule_3_4_3_3_5 }} -rhel8cis_rule_3_4_3_3_6: {{ rhel8cis_rule_3_4_3_3_6 }} - -# Section 4 rules + +## +## Section 4 rules +## +# cron rhel8cis_rule_4_1_1_1: {{ rhel8cis_rule_4_1_1_1 }} rhel8cis_rule_4_1_1_2: {{ rhel8cis_rule_4_1_1_2 }} rhel8cis_rule_4_1_1_3: {{ rhel8cis_rule_4_1_1_3 }} rhel8cis_rule_4_1_1_4: {{ rhel8cis_rule_4_1_1_4 }} +rhel8cis_rule_4_1_1_5: {{ rhel8cis_rule_4_1_1_5 }} +rhel8cis_rule_4_1_1_6: {{ rhel8cis_rule_4_1_1_6 }} +rhel8cis_rule_4_1_1_7: {{ rhel8cis_rule_4_1_1_7 }} +rhel8cis_rule_4_1_1_8: {{ rhel8cis_rule_4_1_1_8 }} +# at rhel8cis_rule_4_1_2_1: {{ rhel8cis_rule_4_1_2_1 }} -rhel8cis_rule_4_1_2_2: {{ rhel8cis_rule_4_1_2_2 }} -rhel8cis_rule_4_1_2_3: {{ rhel8cis_rule_4_1_2_3 }} - -rhel8cis_rule_4_1_3_1: {{ rhel8cis_rule_4_1_3_1 }} -rhel8cis_rule_4_1_3_2: {{ rhel8cis_rule_4_1_3_2 }} -rhel8cis_rule_4_1_3_3: {{ rhel8cis_rule_4_1_3_3 }} -rhel8cis_rule_4_1_3_4: {{ rhel8cis_rule_4_1_3_4 }} -rhel8cis_rule_4_1_3_5: {{ rhel8cis_rule_4_1_3_5 }} -rhel8cis_rule_4_1_3_6: {{ rhel8cis_rule_4_1_3_6 }} -rhel8cis_rule_4_1_3_7: {{ rhel8cis_rule_4_1_3_7 }} -rhel8cis_rule_4_1_3_8: {{ rhel8cis_rule_4_1_3_8 }} -rhel8cis_rule_4_1_3_9: {{ rhel8cis_rule_4_1_3_9 }} -rhel8cis_rule_4_1_3_10: {{ rhel8cis_rule_4_1_3_10 }} -rhel8cis_rule_4_1_3_11: {{ rhel8cis_rule_4_1_3_11 }} -rhel8cis_rule_4_1_3_12: {{ rhel8cis_rule_4_1_3_12 }} -rhel8cis_rule_4_1_3_13: {{ rhel8cis_rule_4_1_3_13 }} -rhel8cis_rule_4_1_3_14: {{ rhel8cis_rule_4_1_3_14 }} -rhel8cis_rule_4_1_3_15: {{ rhel8cis_rule_4_1_3_15 }} -rhel8cis_rule_4_1_3_16: {{ rhel8cis_rule_4_1_3_16 }} -rhel8cis_rule_4_1_3_17: {{ rhel8cis_rule_4_1_3_17 }} -rhel8cis_rule_4_1_3_18: {{ rhel8cis_rule_4_1_3_18 }} -rhel8cis_rule_4_1_3_19: {{ rhel8cis_rule_4_1_3_19 }} -rhel8cis_rule_4_1_3_20: {{ rhel8cis_rule_4_1_3_20 }} -rhel8cis_rule_4_1_3_21: {{ rhel8cis_rule_4_1_3_21 }} - -rhel8cis_rule_4_2_1_1: {{ rhel8cis_rule_4_2_1_1 }} -rhel8cis_rule_4_2_1_2: {{ rhel8cis_rule_4_2_1_2 }} -rhel8cis_rule_4_2_1_3: {{ rhel8cis_rule_4_2_1_3 }} -rhel8cis_rule_4_2_1_4: {{ rhel8cis_rule_4_2_1_4 }} -rhel8cis_rule_4_2_1_5: {{ rhel8cis_rule_4_2_1_5 }} -rhel8cis_rule_4_2_1_6: {{ rhel8cis_rule_4_2_1_6 }} -rhel8cis_rule_4_2_1_7: {{ rhel8cis_rule_4_2_1_7 }} - -rhel8cis_rule_4_2_2_1_1: {{ rhel8cis_rule_4_2_2_1_1 }} -rhel8cis_rule_4_2_2_1_2: {{ rhel8cis_rule_4_2_2_1_2 }} -rhel8cis_rule_4_2_2_1_3: {{ rhel8cis_rule_4_2_2_1_3 }} -rhel8cis_rule_4_2_2_1_4: {{ rhel8cis_rule_4_2_2_1_4 }} - -rhel8cis_rule_4_2_2_2: {{ rhel8cis_rule_4_2_2_2 }} -rhel8cis_rule_4_2_2_3: {{ rhel8cis_rule_4_2_2_3 }} -rhel8cis_rule_4_2_2_4: {{ rhel8cis_rule_4_2_2_4 }} -rhel8cis_rule_4_2_2_5: {{ rhel8cis_rule_4_2_2_5 }} -rhel8cis_rule_4_2_2_6: {{ rhel8cis_rule_4_2_2_6 }} -rhel8cis_rule_4_2_2_7: {{ rhel8cis_rule_4_2_2_7 }} +# sshd +rhel8cis_rule_4_2_1: {{ rhel8cis_rule_4_2_1 }} +rhel8cis_rule_4_2_2: {{ rhel8cis_rule_4_2_2 }} rhel8cis_rule_4_2_3: {{ rhel8cis_rule_4_2_3 }} - -rhel8cis_rule_4_3: {{ rhel8cis_rule_4_3 }} - -# Section 5 -rhel8cis_rule_5_1_1: {{ rhel8cis_rule_5_1_1 }} -rhel8cis_rule_5_1_2: {{ rhel8cis_rule_5_1_2 }} +rhel8cis_rule_4_2_4: {{ rhel8cis_rule_4_2_4 }} +rhel8cis_rule_4_2_5: {{ rhel8cis_rule_4_2_5 }} +rhel8cis_rule_4_2_6: {{ rhel8cis_rule_4_2_6 }} +rhel8cis_rule_4_2_7: {{ rhel8cis_rule_4_2_7 }} +rhel8cis_rule_4_2_8: {{ rhel8cis_rule_4_2_8 }} +rhel8cis_rule_4_2_9: {{ rhel8cis_rule_4_2_9 }} +rhel8cis_rule_4_2_10: {{ rhel8cis_rule_4_2_10 }} +rhel8cis_rule_4_2_12: {{ rhel8cis_rule_4_2_12 }} +rhel8cis_rule_4_2_11: {{ rhel8cis_rule_4_2_11 }} +rhel8cis_rule_4_2_13: {{ rhel8cis_rule_4_2_13 }} +rhel8cis_rule_4_2_14: {{ rhel8cis_rule_4_2_14 }} +rhel8cis_rule_4_2_15: {{ rhel8cis_rule_4_2_15 }} +rhel8cis_rule_4_2_16: {{ rhel8cis_rule_4_2_16 }} +rhel8cis_rule_4_2_17: {{ rhel8cis_rule_4_2_17 }} +rhel8cis_rule_4_2_18: {{ rhel8cis_rule_4_2_18 }} +rhel8cis_rule_4_2_19: {{ rhel8cis_rule_4_2_19 }} +rhel8cis_rule_4_2_20: {{ rhel8cis_rule_4_2_20 }} +rhel8cis_rule_4_2_21: {{ rhel8cis_rule_4_2_21 }} +rhel8cis_rule_4_2_22: {{ rhel8cis_rule_4_2_22 }} + +# sudo +rhel8cis_rule_4_3_1: {{ rhel8cis_rule_4_3_1 }} +rhel8cis_rule_4_3_2: {{ rhel8cis_rule_4_3_2 }} +rhel8cis_rule_4_3_3: {{ rhel8cis_rule_4_3_3 }} +rhel8cis_rule_4_3_4: {{ rhel8cis_rule_4_3_4 }} +rhel8cis_rule_4_3_5: {{ rhel8cis_rule_4_3_5 }} +rhel8cis_rule_4_3_6: {{ rhel8cis_rule_4_3_6 }} +rhel8cis_rule_4_3_7: {{ rhel8cis_rule_4_3_7 }} + +# Pam software pkgs +rhel8cis_rule_4_4_1_1: {{ rhel8cis_rule_4_4_1_1 }} +rhel8cis_rule_4_4_1_2: {{ rhel8cis_rule_4_4_1_2 }} + +# authselect +rhel8cis_rule_4_4_2_1: {{ rhel8cis_rule_4_4_2_1 }} +rhel8cis_rule_4_4_2_2: {{ rhel8cis_rule_4_4_2_2 }} +rhel8cis_rule_4_4_2_3: {{ rhel8cis_rule_4_4_2_3 }} +rhel8cis_rule_4_4_2_4: {{ rhel8cis_rule_4_4_2_4 }} +rhel8cis_rule_4_4_2_5: {{ rhel8cis_rule_4_4_2_5 }} + +# pam faillock +rhel8cis_rule_4_4_3_1_1: {{ rhel8cis_rule_4_4_3_1_1 }} +rhel8cis_rule_4_4_3_1_2: {{ rhel8cis_rule_4_4_3_1_2 }} +rhel8cis_rule_4_4_3_1_3: {{ rhel8cis_rule_4_4_3_1_3 }} + +# pam pwquality +rhel8cis_rule_4_4_3_2_1: {{ rhel8cis_rule_4_4_3_2_1 }} +rhel8cis_rule_4_4_3_2_2: {{ rhel8cis_rule_4_4_3_2_2 }} +rhel8cis_rule_4_4_3_2_3: {{ rhel8cis_rule_4_4_3_2_3 }} +rhel8cis_rule_4_4_3_2_4: {{ rhel8cis_rule_4_4_3_2_4 }} +rhel8cis_rule_4_4_3_2_5: {{ rhel8cis_rule_4_4_3_2_5 }} +rhel8cis_rule_4_4_3_2_6: {{ rhel8cis_rule_4_4_3_2_6 }} +rhel8cis_rule_4_4_3_2_7: {{ rhel8cis_rule_4_4_3_2_7 }} + +# pam pwhistory +rhel8cis_rule_4_4_3_3_1: {{ rhel8cis_rule_4_4_3_3_1 }} +rhel8cis_rule_4_4_3_3_2: {{ rhel8cis_rule_4_4_3_3_2 }} +rhel8cis_rule_4_4_3_3_3: {{ rhel8cis_rule_4_4_3_3_3 }} + +# pam pam_unix +rhel8cis_rule_4_4_3_4_1: {{ rhel8cis_rule_4_4_3_4_1 }} +rhel8cis_rule_4_4_3_4_2: {{ rhel8cis_rule_4_4_3_4_2 }} +rhel8cis_rule_4_4_3_4_3: {{ rhel8cis_rule_4_4_3_4_3 }} +rhel8cis_rule_4_4_3_4_4: {{ rhel8cis_rule_4_4_3_4_4 }} + +# Shadow user settings +rhel8cis_rule_4_5_1_1: {{ rhel8cis_rule_4_5_1_1 }} +rhel8cis_rule_4_5_1_2: {{ rhel8cis_rule_4_5_1_2 }} +rhel8cis_rule_4_5_1_3: {{ rhel8cis_rule_4_5_1_3 }} +rhel8cis_rule_4_5_1_4: {{ rhel8cis_rule_4_5_1_4 }} +rhel8cis_rule_4_5_1_5: {{ rhel8cis_rule_4_5_1_5 }} + +# root and sys accts and env +rhel8cis_rule_4_5_2_1: {{ rhel8cis_rule_4_5_2_1 }} +rhel8cis_rule_4_5_2_2: {{ rhel8cis_rule_4_5_2_2 }} +rhel8cis_rule_4_5_2_3: {{ rhel8cis_rule_4_5_2_3 }} +rhel8cis_rule_4_5_2_4: {{ rhel8cis_rule_4_5_2_4 }} +rhel8cis_rule_4_5_2_5: {{ rhel8cis_rule_4_5_2_5 }} + +# User enviroment +rhel8cis_rule_4_5_3_1: {{ rhel8cis_rule_4_5_3_1 }} +rhel8cis_rule_4_5_3_2: {{ rhel8cis_rule_4_5_3_2 }} +rhel8cis_rule_4_5_3_3: {{ rhel8cis_rule_4_5_3_3 }} + +## +## Section 5 rules +## + +# Rsyslog +rhel8cis_rule_5_1_1_1: {{ rhel8cis_rule_5_1_1_1 }} +rhel8cis_rule_5_1_1_2: {{ rhel8cis_rule_5_1_1_2 }} +rhel8cis_rule_5_1_1_3: {{ rhel8cis_rule_5_1_1_3 }} +rhel8cis_rule_5_1_1_4: {{ rhel8cis_rule_5_1_1_4 }} +rhel8cis_rule_5_1_1_5: {{ rhel8cis_rule_5_1_1_5 }} +rhel8cis_rule_5_1_1_6: {{ rhel8cis_rule_5_1_1_6 }} +rhel8cis_rule_5_1_1_7: {{ rhel8cis_rule_5_1_1_7 }} + +# Journald +rhel8cis_rule_5_1_2_1_1: {{ rhel8cis_rule_5_1_2_1_1 }} +rhel8cis_rule_5_1_2_1_2: {{ rhel8cis_rule_5_1_2_1_2 }} +rhel8cis_rule_5_1_2_1_3: {{ rhel8cis_rule_5_1_2_1_3 }} +rhel8cis_rule_5_1_2_1_4: {{ rhel8cis_rule_5_1_2_1_4 }} +rhel8cis_rule_5_1_2_2: {{ rhel8cis_rule_5_1_2_2 }} +rhel8cis_rule_5_1_2_3: {{ rhel8cis_rule_5_1_2_3 }} +rhel8cis_rule_5_1_2_4: {{ rhel8cis_rule_5_1_2_4 }} +rhel8cis_rule_5_1_2_5: {{ rhel8cis_rule_5_1_2_5 }} +rhel8cis_rule_5_1_2_6: {{ rhel8cis_rule_5_1_2_6 }} rhel8cis_rule_5_1_3: {{ rhel8cis_rule_5_1_3 }} rhel8cis_rule_5_1_4: {{ rhel8cis_rule_5_1_4 }} -rhel8cis_rule_5_1_5: {{ rhel8cis_rule_5_1_5 }} -rhel8cis_rule_5_1_6: {{ rhel8cis_rule_5_1_6 }} -rhel8cis_rule_5_1_7: {{ rhel8cis_rule_5_1_7 }} -rhel8cis_rule_5_1_8: {{ rhel8cis_rule_5_1_8 }} -rhel8cis_rule_5_1_9: {{ rhel8cis_rule_5_1_9 }} - -rhel8cis_rule_5_2_1: {{ rhel8cis_rule_5_2_1 }} -rhel8cis_rule_5_2_2: {{ rhel8cis_rule_5_2_2 }} -rhel8cis_rule_5_2_3: {{ rhel8cis_rule_5_2_3 }} -rhel8cis_rule_5_2_4: {{ rhel8cis_rule_5_2_4 }} -rhel8cis_rule_5_2_5: {{ rhel8cis_rule_5_2_5 }} -rhel8cis_rule_5_2_6: {{ rhel8cis_rule_5_2_6 }} -rhel8cis_rule_5_2_7: {{ rhel8cis_rule_5_2_7 }} -rhel8cis_rule_5_2_8: {{ rhel8cis_rule_5_2_8 }} -rhel8cis_rule_5_2_9: {{ rhel8cis_rule_5_2_9 }} -rhel8cis_rule_5_2_10: {{ rhel8cis_rule_5_2_10 }} -rhel8cis_rule_5_2_11: {{ rhel8cis_rule_5_2_11 }} -rhel8cis_rule_5_2_12: {{ rhel8cis_rule_5_2_12 }} -rhel8cis_rule_5_2_13: {{ rhel8cis_rule_5_2_13 }} -rhel8cis_rule_5_2_14: {{ rhel8cis_rule_5_2_14 }} -rhel8cis_rule_5_2_15: {{ rhel8cis_rule_5_2_15 }} -rhel8cis_rule_5_2_16: {{ rhel8cis_rule_5_2_16 }} -rhel8cis_rule_5_2_17: {{ rhel8cis_rule_5_2_17 }} -rhel8cis_rule_5_2_18: {{ rhel8cis_rule_5_2_18 }} -rhel8cis_rule_5_2_19: {{ rhel8cis_rule_5_2_19 }} -rhel8cis_rule_5_2_20: {{ rhel8cis_rule_5_2_20 }} + +# Auditd +rhel8cis_rule_5_2_1_1: {{ rhel8cis_rule_5_2_1_1 }} +rhel8cis_rule_5_2_1_2: {{ rhel8cis_rule_5_2_1_2 }} +rhel8cis_rule_5_2_1_3: {{ rhel8cis_rule_5_2_1_3 }} +rhel8cis_rule_5_2_1_4: {{ rhel8cis_rule_5_2_1_4 }} +rhel8cis_rule_5_2_2_1: {{ rhel8cis_rule_5_2_2_1 }} +rhel8cis_rule_5_2_2_2: {{ rhel8cis_rule_5_2_2_2 }} +rhel8cis_rule_5_2_2_3: {{ rhel8cis_rule_5_2_2_3 }} +rhel8cis_rule_5_2_2_4: {{ rhel8cis_rule_5_2_2_4 }} + +# auditd rules +rhel8cis_rule_5_2_3_1: {{ rhel8cis_rule_5_2_3_1 }} +rhel8cis_rule_5_2_3_2: {{ rhel8cis_rule_5_2_3_2 }} +rhel8cis_rule_5_2_3_3: {{ rhel8cis_rule_5_2_3_3 }} +rhel8cis_rule_5_2_3_4: {{ rhel8cis_rule_5_2_3_4 }} +rhel8cis_rule_5_2_3_5: {{ rhel8cis_rule_5_2_3_5 }} +rhel8cis_rule_5_2_3_6: {{ rhel8cis_rule_5_2_3_6 }} +rhel8cis_rule_5_2_3_7: {{ rhel8cis_rule_5_2_3_7 }} +rhel8cis_rule_5_2_3_8: {{ rhel8cis_rule_5_2_3_8 }} +rhel8cis_rule_5_2_3_9: {{ rhel8cis_rule_5_2_3_9 }} +rhel8cis_rule_5_2_3_10: {{ rhel8cis_rule_5_2_3_10 }} +rhel8cis_rule_5_2_3_11: {{ rhel8cis_rule_5_2_3_11 }} +rhel8cis_rule_5_2_3_12: {{ rhel8cis_rule_5_2_3_12 }} +rhel8cis_rule_5_2_3_13: {{ rhel8cis_rule_5_2_3_13 }} +rhel8cis_rule_5_2_3_14: {{ rhel8cis_rule_5_2_3_14 }} +rhel8cis_rule_5_2_3_15: {{ rhel8cis_rule_5_2_3_15 }} +rhel8cis_rule_5_2_3_16: {{ rhel8cis_rule_5_2_3_16 }} +rhel8cis_rule_5_2_3_17: {{ rhel8cis_rule_5_2_3_17 }} +rhel8cis_rule_5_2_3_18: {{ rhel8cis_rule_5_2_3_18 }} +rhel8cis_rule_5_2_3_19: {{ rhel8cis_rule_5_2_3_19 }} +rhel8cis_rule_5_2_3_20: {{ rhel8cis_rule_5_2_3_20 }} +rhel8cis_rule_5_2_3_21: {{ rhel8cis_rule_5_2_3_21 }} + +# auditd log perms +rhel8cis_rule_5_2_4_1: {{ rhel8cis_rule_5_2_4_1 }} +rhel8cis_rule_5_2_4_2: {{ rhel8cis_rule_5_2_4_2 }} +rhel8cis_rule_5_2_4_3: {{ rhel8cis_rule_5_2_4_3 }} +rhel8cis_rule_5_2_4_4: {{ rhel8cis_rule_5_2_4_4 }} +rhel8cis_rule_5_2_4_5: {{ rhel8cis_rule_5_2_4_5 }} +rhel8cis_rule_5_2_4_6: {{ rhel8cis_rule_5_2_4_6 }} +rhel8cis_rule_5_2_4_7: {{ rhel8cis_rule_5_2_4_7 }} +rhel8cis_rule_5_2_4_8: {{ rhel8cis_rule_5_2_4_8 }} +rhel8cis_rule_5_2_4_9: {{ rhel8cis_rule_5_2_4_9 }} +rhel8cis_rule_5_2_4_10: {{ rhel8cis_rule_5_2_4_10 }} + +# AIDE rhel8cis_rule_5_3_1: {{ rhel8cis_rule_5_3_1 }} rhel8cis_rule_5_3_2: {{ rhel8cis_rule_5_3_2 }} rhel8cis_rule_5_3_3: {{ rhel8cis_rule_5_3_3 }} -rhel8cis_rule_5_3_4: {{ rhel8cis_rule_5_3_4 }} -rhel8cis_rule_5_3_5: {{ rhel8cis_rule_5_3_5 }} -rhel8cis_rule_5_3_6: {{ rhel8cis_rule_5_3_6 }} -rhel8cis_rule_5_3_7: {{ rhel8cis_rule_5_3_7 }} - -rhel8cis_rule_5_4_1: {{ rhel8cis_rule_5_4_1 }} -rhel8cis_rule_5_4_2: {{ rhel8cis_rule_5_4_2 }} - -rhel8cis_rule_5_5_1: {{ rhel8cis_rule_5_5_1 }} -rhel8cis_rule_5_5_2: {{ rhel8cis_rule_5_5_2 }} -rhel8cis_rule_5_5_3: {{ rhel8cis_rule_5_5_3 }} -rhel8cis_rule_5_5_4: {{ rhel8cis_rule_5_5_4 }} - -rhel8cis_rule_5_6_1_1: {{ rhel8cis_rule_5_6_1_1 }} -rhel8cis_rule_5_6_1_2: {{ rhel8cis_rule_5_6_1_2 }} -rhel8cis_rule_5_6_1_3: {{ rhel8cis_rule_5_6_1_3 }} -rhel8cis_rule_5_6_1_4: {{ rhel8cis_rule_5_6_1_4 }} -rhel8cis_rule_5_6_1_5: {{ rhel8cis_rule_5_6_1_5 }} - -rhel8cis_rule_5_6_2: {{ rhel8cis_rule_5_6_2 }} -rhel8cis_rule_5_6_3: {{ rhel8cis_rule_5_6_3 }} -rhel8cis_rule_5_6_4: {{ rhel8cis_rule_5_6_4 }} -rhel8cis_rule_5_6_5: {{ rhel8cis_rule_5_6_5 }} - -# Section 6 + +## +## Section 6 rules +## + +# System file perms rhel8cis_rule_6_1_1: {{ rhel8cis_rule_6_1_1 }} rhel8cis_rule_6_1_2: {{ rhel8cis_rule_6_1_2 }} rhel8cis_rule_6_1_3: {{ rhel8cis_rule_6_1_3 }} @@ -333,8 +406,8 @@ rhel8cis_rule_6_1_11: {{ rhel8cis_rule_6_1_11 }} rhel8cis_rule_6_1_12: {{ rhel8cis_rule_6_1_12 }} rhel8cis_rule_6_1_13: {{ rhel8cis_rule_6_1_13 }} rhel8cis_rule_6_1_14: {{ rhel8cis_rule_6_1_14 }} -rhel8cis_rule_6_1_15: {{ rhel8cis_rule_6_1_15 }} +# local and usergroup rhel8cis_rule_6_2_1: {{ rhel8cis_rule_6_2_1 }} rhel8cis_rule_6_2_2: {{ rhel8cis_rule_6_2_2 }} rhel8cis_rule_6_2_3: {{ rhel8cis_rule_6_2_3 }} @@ -346,159 +419,331 @@ rhel8cis_rule_6_2_8: {{ rhel8cis_rule_6_2_8 }} rhel8cis_rule_6_2_9: {{ rhel8cis_rule_6_2_9 }} rhel8cis_rule_6_2_10: {{ rhel8cis_rule_6_2_10 }} rhel8cis_rule_6_2_11: {{ rhel8cis_rule_6_2_11 }} -rhel8cis_rule_6_2_12: {{ rhel8cis_rule_6_2_12 }} -rhel8cis_rule_6_2_13: {{ rhel8cis_rule_6_2_13 }} -rhel8cis_rule_6_2_14: {{ rhel8cis_rule_6_2_14 }} -rhel8cis_rule_6_2_15: {{ rhel8cis_rule_6_2_15 }} -rhel8cis_rule_6_2_16: {{ rhel8cis_rule_6_2_16 }} -# Service configuration booleans set true to keep service +## +## Section 1 vars +## +# 1.1.2.2 +# 1.1.2.3 +# 1.1.2.4 +# These settings go into the /etc/fstab file for the /tmp mount settings +# The value must contain nosuid,nodev,noexec to conform to CIS standards +# rhel8cis_tmp_tmpfs_settings: "defaults,rw,nosuid,nodev,noexec,relatime 0 0" +# If set true uses the tmp.mount service else using fstab configuration +rhel8cis_tmp_svc: {{ rhel8cis_tmp_svc }} + +# 1.2 patch system +rhel8cis_apply_installed_kernel_limit: {{ rhel8cis_apply_installed_kernel_limit }} +rhel8cis_installed_kernel_limit: {{ rhel8cis_installed_kernel_limit }} + +# 1.3 Bootloader password +rhel8cis_bootloader_password_hash: {{ rhel8cis_bootloader_password_hash }} +rhel8cis_bootloader_password: {{ rhel8cis_bootloader_password }} +rhel8cis_set_boot_pass: {{ rhel8cis_set_boot_pass }} +rhel8cis_boot_path: {{ rhel8cis_boot_path }} + +# 1.5 SELinux policy +rhel8cis_selinux_pol: {{ rhel8cis_selinux_pol }} + +# 1.6 Set crypto policy (LEGACY, DEFAULT, FUTURE, FIPS) +rhel8cis_crypto_policy: {{ rhel8cis_crypto_policy }} +# Added module to be allowed as default setting (Allowed options in vars/main.yml) +rhel8cis_crypto_policy_module: {{ rhel8cis_crypto_policy_module }} + +# 1.7 +# Warning Banner Content (issue, issue.net, motd) +rhel8cis_warning_banner: {{ rhel8cis_warning_banner }} +# End Banner + +# 1.8 Gnome Desktop +# Whether or not to run tasks related to auditing/patching the desktop environment +rhel8cis_gui: {{ rhel8cis_gui }} +rhel8cis_dconf_db_name: {{ rhel8cis_dconf_db_name }} +rhel8cis_screensaver_idle_delay: {{ rhel8cis_screensaver_idle_delay }} # Set max value for idle-delay in seconds (between 1 and 900) +rhel8cis_screensaver_lock_delay: {{ rhel8cis_screensaver_lock_delay }} # Set max value for lock-delay in seconds (between 0 and 5) +## +## Section 2 vars +## +# 2.1.1 Time Synchronization - Either chrony or ntp +rhel8cis_time_synchronization: {{ rhel8cis_time_synchronization }} + +# Time Synchronization servers - used in template file chrony.conf.j2 +rhel8cis_time_synchronization_servers: +{% for server in rhel8cis_time_synchronization_servers %} + - {{ server }} +{% endfor %} + +rhel8cis_chrony_server_options: "{{ rhel8cis_chrony_server_options }}" +rhel8cis_ntp_server_options: "{{ rhel8cis_ntp_server_options }}" + +# Service configuration +# Options are +# true to leave installed if exists not changes take place +# false - this removes the package +# mask - if a dependancy for product so cannot be removed +# Server Services +rhel8cis_autofs_services: {{ rhel8cis_autofs_services }} +rhel8cis_autofs_mask: {{ rhel8cis_autofs_mask }} rhel8cis_avahi_server: {{ rhel8cis_avahi_server }} -rhel8cis_cups_server: {{ rhel8cis_cups_server }} +rhel8cis_avahi_mask: {{ rhel8cis_avahi_mask }} rhel8cis_dhcp_server: {{ rhel8cis_dhcp_server }} +rhel8cis_dhcp_mask: {{ rhel8cis_dhcp_mask }} rhel8cis_dns_server: {{ rhel8cis_dns_server }} -rhel8cis_dovecot_cyrus_server: {{ rhel8cis_dovecot_cyrus_server }} +rhel8cis_dns_mask: {{ rhel8cis_dns_mask }} +rhel8cis_dnsmasq_server: {{ rhel8cis_dnsmasq_server }} +rhel8cis_dnsmasq_mask: {{ rhel8cis_dnsmasq_mask }} +rhel8cis_samba_server: {{ rhel8cis_samba_server }} +rhel8cis_samba_mask: {{ rhel8cis_samba_mask }} rhel8cis_ftp_server: {{ rhel8cis_ftp_server }} -rhel8cis_httpd_server: {{ rhel8cis_httpd_server }} -rhel8cis_is_mail_server: {{ rhel8cis_is_mail_server }} -rhel8cis_net_snmp_server: {{ rhel8cis_net_snmp_server }} +rhel8cis_ftp_mask: {{ rhel8cis_ftp_mask }} +rhel8cis_message_server: {{ rhel8cis_message_server }} # This is for messaging dovecot and cyrus-imap +rhel8cis_message_mask: {{ rhel8cis_message_mask }} rhel8cis_nfs_server: {{ rhel8cis_nfs_server }} -rhel8cis_nginx_server: {{ rhel8cis_nginx_server }} -rhel8cis_nis_server: {{ rhel8cis_nis_server }} +rhel8cis_nfs_mask: {{ rhel8cis_nfs_mask }} +rhel8cis_nis_server: {{ rhel8cis_nis_server }} # set to mask if nis client required +rhel8cis_nis_mask: {{ rhel8cis_nis_mask }} +rhel8cis_print_server: {{ rhel8cis_print_server }} # replaces cups +rhel8cis_print_mask: {{ rhel8cis_print_mask }} rhel8cis_rpc_server: {{ rhel8cis_rpc_server }} +rhel8cis_rpc_mask: {{ rhel8cis_rpc_mask }} rhel8cis_rsync_server: {{ rhel8cis_rsync_server }} -rhel8cis_samba_server: {{ rhel8cis_samba_server }} -rhel8cis_squid_server: {{ rhel8cis_squid_server }} +rhel8cis_rsync_mask: {{ rhel8cis_rsync_mask }} +rhel8cis_net_snmp_server: {{ rhel8cis_net_snmp_server }} +rhel8cis_net_snmp_mask: {{ rhel8cis_net_snmp_mask }} rhel8cis_telnet_server: {{ rhel8cis_telnet_server }} +rhel8cis_telnet_mask: {{ rhel8cis_telnet_mask }} rhel8cis_tftp_server: {{ rhel8cis_tftp_server }} -rhel8cis_vsftpd_server: {{ rhel8cis_vsftpd_server }} - -rhel8cis_allow_autofs: {{ rhel8cis_allow_autofs }} +rhel8cis_tftp_mask: {{ rhel8cis_tftp_mask }} +rhel8cis_squid_server: {{ rhel8cis_squid_server }} +rhel8cis_squid_mask: {{ rhel8cis_squid_mask }} +rhel8cis_httpd_server: {{ rhel8cis_httpd_server }} +rhel8cis_httpd_mask: {{ rhel8cis_httpd_mask }} +rhel8cis_nginx_server: {{ rhel8cis_nginx_server }} +rhel8cis_nginx_mask: {{ rhel8cis_nginx_mask }} +rhel8cis_xinetd_server: {{ rhel8cis_xinetd_server }} +rhel8cis_xinetd_mask: {{ rhel8cis_xinetd_mask }} +rhel8cis_xwindow_server: {{ rhel8cis_xwindow_server }} # will remove mask not an option +rhel8cis_is_mail_server: {{ rhel8cis_is_mail_server }} -# client services +# Client Services +rhel8cis_ftp_client: {{ rhel8cis_ftp_client }} rhel8cis_openldap_clients_required: {{ rhel8cis_openldap_clients_required }} +rhel8cis_ypbind_required: {{ rhel8cis_ypbind_required }} # Same package as NIS server rhel8cis_telnet_required: {{ rhel8cis_telnet_required }} -rhel8cis_talk_required: {{ rhel8cis_talk_required }} -rhel8cis_rsh_required: {{ rhel8cis_rsh_required }} -rhel8cis_ypbind_required: {{ rhel8cis_ypbind_required }} -rhel8cis_tftp_required: {{ rhel8cis_tftp_client }} +rhel8cis_tftp_client: {{ rhel8cis_tftp_client }} -# AIDE -rhel8cis_config_aide: {{ rhel8cis_config_aide }} +## +## Section 3 vars +## -# aide setup via - cron, timer -rhel8_aide_scan: cron +rhel8cis_bluetooth_service: {{ rhel8cis_bluetooth_service }} +rhel8cis_bluetooth_mask: {{ rhel8cis_bluetooth_mask }} -# AIDE cron settings -rhel8cis_aide_cron: - cron_user: {{ rhel8cis_aide_cron.cron_user }} - cron_file: '{{ rhel8cis_aide_cron.cron_file }}' - aide_job: ' {{ rhel8cis_aide_cron.aide_job }}' - aide_minute: '{{ rhel8cis_aide_cron.aide_minute }}' - aide_hour: '{{ rhel8cis_aide_cron.aide_hour }}' - aide_day: '{{ rhel8cis_aide_cron.aide_day }}' - aide_month: '{{ rhel8cis_aide_cron.aide_month }}' - aide_weekday: '{{ rhel8cis_aide_cron.aide_weekday }}' - -# 1.5.1 Bootloader password -rhel8cis_bootloader_password: {{ rhel8cis_bootloader_password_hash }} -rhel8cis_set_boot_pass: {{ rhel8cis_set_boot_pass }} +# System network parameters (host only OR host and router) +rhel8cis_is_router: {{ rhel8cis_is_router }} -# 1.10 crypto -rhel8cis_crypto_policy: {{ rhel8cis_crypto_policy }} +# IPv6 required +rhel8cis_ipv6_required: {{ rhel8cis_ipv6_required }} -# Warning Banner Content (issue, issue.net, motd) -rhel8cis_warning_banner: {{ rhel8cis_warning_banner }} -# End Banner +rhel8cis_ipv6_sysctl_force: {{ rhel8cis_ipv6_sysctl_force }} + +## Optional - Understand the impact of making the following two control to true +# By default, we do not disable IPv6 on localhost, as it's important for multiple +# components. If you want to disable it anyway, change the following +# value to true refer https://access.redhat.com/solutions/8709 +# this changes sysctl and /etc/hosts +# requires reboot +rhel8cis_ipv6_disable_localhost: {{ rhel8cis_ipv6_disable_localhost }} +# disable ipv6 for sshd +rhel8cis_ipv6_sshd_disable: {{ rhel8cis_ipv6_sshd_disable }} +# disable chrony on ipv6 +rhel8cis_ipv6_chrony_disable: {{ rhel8cis_ipv6_chrony_disable }} # Set to 'true' if X Windows is needed in your environment rhel8cis_xwindows_required: {{ rhel8cis_xwindows_required }} -# Whether or not to run tasks related to auditing/patching the desktop environment -rhel8cis_gui: {{ rhel8cis_gui }} +## Section3 vars -# xinetd required -rhel8cis_xinetd_required: {{ rhel8cis_xinetd_required }} +# default location for the sysctl overrides. +rhel8cis_sysctl_file: {{ rhel8cis_sysctl_file }} -# IPv6 required -rhel8cis_ipv6_required: {{ rhel8cis_ipv6_required }} +# Firewall Service - either firewalld or nftables +rhel8cis_firewall: {{ rhel8cis_firewall }} -# System network parameters (host only OR host and router) -rhel8cis_is_router: {{ rhel8cis_is_router }} +rhel8cis_default_zone: {{ rhel8cis_default_zone }} + +rhel8cis_nft_tables_autonewtable: {{ rhel8cis_nft_tables_autonewtable }} +rhel8cis_nft_tables_tablename: {{ rhel8cis_nft_tables_tablename }} + +# 3.4.2.6 Set nftables new chain create +rhel8cis_nft_tables_autochaincreate: {{ rhel8cis_nft_tables_autochaincreate }} + +####### +## Section4 vars +###### +## If using the allow/deny user groups options +rhel8cis_sshd_limited: {{ rhel8cis_sshd_limited }} +rhel8cis_sshd: + clientalivecountmax: {{ rhel8cis_sshd.clientalivecountmax }} + clientaliveinterval: {{ rhel8cis_sshd.clientaliveinterval }} + logingracetime: {{ rhel8cis_sshd.logingracetime }} + loglevel: {{ rhel8cis_sshd.loglevel }} + macs: '{{ rhel8cis_sshd.macs }}' + maxauthtries: {{ rhel8cis_sshd.maxauthtries }} + maxsessions: {{ rhel8cis_sshd.maxsessions }} + maxstartups: '{{ rhel8cis_sshd.maxstartups }}' + ciphers: '{{ rhel8cis_sshd.ciphers }}' + kex: '{{ rhel8cis_sshd.kex }}' +{% if rhel8cis_sshd_limited %} + # WARNING: make sure you understand the precedence when working with these values!! + {% if rhel8cis_sshd.allowusers is defined %} + # allowusers: '{{ rhel8cis_sshd.allowusers }}' + {% endif %} + {% if rhel8cis_sshd.allowgroups is defined %} + # allowgroups: '{{ rhel8cis_sshd.allowgroups }}' + {% endif %} + {% if rhel8cis_sshd.denyusers is defined %} + # denyusers: '{{ rhel8cis_sshd.denyusers }}' + {% endif %} + {% if rhel8cis_sshd.denygroups is defined %} + # denygroups: '{{ rhel8cis_sshd.denygroups }}' + {% endif %} +{% endif %} -# Time Synchronization -rhel8cis_time_synchronization: {{ rhel8cis_time_synchronization }} +# 4.3. sudo +rhel8cis_sudolog_location: "{{ rhel8cis_sudolog_location }}" +rhel8cis_sudo_timestamp_timeout: {{ rhel8cis_sudo_timestamp_timeout }} -rhel8cis_sudolog_location: {{ rhel8cis_sudolog_location }} +## PAM +# 4.4.2.x +rhel8cis_authselect_pkg_update: {{ rhel8cis_authselect_pkg_update }} # NOTE the risks if system is using SSSD or using ipa-client-install +rhel8cis_allow_authselect_updates: {{ rhel8cis_allow_authselect_updates }} +rhel8cis_authselect_custom_profile_create: {{ rhel8cis_authselect_custom_profile_create }} +rhel8cis_authselect_custom_profile_select: {{ rhel8cis_authselect_custom_profile_select }} +rhel8cis_authselect: + custom_profile_name: '{{ rhel8cis_authselect.custom_profile_name }}' + default_file_to_copy: "{{ rhel8cis_authselect.default_file_to_copy }}" + options: {{ rhel8cis_authselect }} + +rhel8cis_pam_faillock: + attempts: {{ rhel8cis_pam_faillock.attempts }} + deny: {{ rhel8cis_pam_faillock.deny }} + interval: {{ rhel8cis_pam_faillock.interval }} + unlock_time: {{ rhel8cis_pam_faillock.unlock_time }} + root_unlock_time: {{ rhel8cis_pam_faillock.root_unlock_time }} + # Choose options below for root options + root_option: {{ rhel8cis_pam_faillock.root_option }} + +rhel8cis_pam_pwquality: + difok: {{ rhel8cis_pam_pwquality.difok }} + maxrepeat: {{ rhel8cis_pam_pwquality.maxrepeat }} + maxseq: {{ rhel8cis_pam_pwquality.maxseq }} + minlen: {{ rhel8cis_pam_pwquality.minlen }} + minclass: {{ rhel8cis_pam_pwquality.minclass }} + +rhel8cis_pam_pwhistory: + remember: {{ rhel8cis_pam_pwhistory }} + +rhel8cis_pam_pwhash: {{ rhel8cis_pam_pwhash }} -rhel8cis_firewall: {{ rhel8cis_firewall }} -#rhel8cis_firewall: iptables -rhel8cis_default_firewall_zone: {{ rhel8cis_default_zone }} -rhel8cis_firewall_interface: -- enp0s3 -- enp0s8 +rhel8cis_pass: + inactive: {{ rhel8cis_pass.inactive }} + max_days: {{ rhel8cis_pass.max_days }} + min_days: {{ rhel8cis_pass.min_days }} + warn_age: {{ rhel8cis_pass.warn_age }} -rhel8cis_firewall_services: {% for svc in rhel8cis_firewall_services %}{{ svc }} {% endfor %} +rhel8cis_root_umask: {{ rhel8cis_root_umask }} # 0027 or more restrictive -### Section 4 -## auditd settings -rhel8cis_auditd: - space_left_action: {{ rhel8cis_auditd.space_left_action}} - action_mail_acct: {{ rhel8cis_auditd.action_mail_acct }} - admin_space_left_action: {{ rhel8cis_auditd.admin_space_left_action }} - max_log_file_action: {{ rhel8cis_auditd.max_log_file_action }} - auditd_backlog_limit: {{ rhel8cis_audit_back_log_limit }} +rhel8cis_shell_session_timeout: + file: {{ rhel8cis_shell_session_timeout.file }} + timeout: {{ rhel8cis_shell_session_timeout.timeout }} -## syslog -rhel8cis_syslog: {{ rhel8cis_syslog }} +# 5.3.7 +rhel8cis_sugroup: {{ rhel8cis_sugroup }} -### Section 5 -rhel8cis_sshd_limited: false -#Note the following to understand precedence and layout -rhel8cis_sshd_access: - AllowUser: - AllowGroup: - DenyUser: - DenyGroup: +# wheel users list +rhel8cis_sugroup_users: "{{ rhel8cis_sugroup_users }}" -rhel8cis_ssh_aliveinterval: "300" -rhel8cis_ssh_countmax: "3" +rhel8cis_inactivelock: + lock_days: {{ rhel8cis_inactivelock.lock_days }} -## PAM -rhel8cis_pam_password: - minlen: {{ rhel8cis_pam_password.minlen }} - minclass: {{ rhel8cis_pam_password.minclass }} -rhel8cis_pam_passwd_retry: "3" -# faillock or tally2 -rhel8cis_accountlock: faillock - -## note this is to skip tests -skip_rhel8cis_pam_passwd_auth: true -skip_rhel8cis_pam_system_auth: true - -# choose one of below -rhel8cis_pwhistory_so: "14" -rhel8cis_unix_so: false -rhel8cis_passwd_remember: "5" - -# logins.def password settings -rhel8cis_pass: - max_days: {{ rhel8cis_pass.max_days }} - min_days: {{ rhel8cis_pass.min_days }} - warn_age: {{ rhel8cis_pass.warn_age }} +# 5.6.1.5 Allow ansible to expire password for account with a last changed date in the future. False will just display users in violation, true will expire those users passwords +rhel8cis_futurepwchgdate_autofix: {{ rhel8cis_futurepwchgdate_autofix }} -# 5.3.1/5.3.2 Custon authselect profile settings. Settings in place now will fail, they are place holders from the control example -rhel8cis_authselect: - custom_profile_name: {{ rhel8cis_authselect['custom_profile_name'] }} - default_file_to_copy: {{ rhel8cis_authselect.default_file_to_copy }} - options: {{ rhel8cis_authselect.options }} +# This is a dynamic check but can be overridden here marking it as false and uncomment +rhel8uid_info_dynamic: "{{ rhel8uid_info_dynamic }}" +# rhel8uid_interactive_uid_start: {{ rhel8uid_interactive_uid_start }} +# rhel8uid_interactive_uid_stop: {{ rhel8uid_interactive_uid_stop }} -# 5.3.1 Enable automation to creat custom profile settings, using the setings above -rhel8cis_authselect_custom_profile_create: {{ rhel8cis_authselect_custom_profile_create }} +## Section5 vars -# 5.3.2 Enable automation to select custom profile options, using the settings above -rhel8cis_authselect_custom_profile_select: {{ rhel8cis_authselect_custom_profile_select }} +## Preferred method of logging +## Whether rsyslog or journald preferred method for local logging +rhel8cis_syslog: {{ rhel8cis_syslog }} +rhel8cis_rsyslog_ansiblemanaged: {{ rhel8cis_rsyslog_ansiblemanaged }} +# Set if system is the log server +rhel8cis_system_is_log_server: {{ rhel8cis_system_is_log_server }} + +#### remote and destination log server name +rhel8cis_remote_log_server: {{ rhel8cis_remote_log_server }} +rhel8cis_remote_log_host: {{ rhel8cis_remote_log_host }} +rhel8cis_remote_log_port: {{ rhel8cis_remote_log_port }} +rhel8cis_remote_log_protocol: {{ rhel8cis_remote_log_protocol }} +rhel8cis_remote_log_retrycount: {{ rhel8cis_remote_log_retrycount }} +rhel8cis_remote_log_queuesize: {{ rhel8cis_remote_log_queuesize }} -# 5.7 -rhel8cis_sugroup: {{ rhel8cis_sugroup| default('wheel') }} -rhel8cis_sugroup_users: {{ rhel8cis_sugroup_users }} +update_audit_template: {{ update_audit_template }} + +rhel8cis_auditd: + disk_error_action: {{ rhel8cis_auditd.disk_error_action }} + disk_full_action: {{ rhel8cis_auditd.disk_full_action }} + action_mail_acct: {{ rhel8cis_auditd.action_mail_acct }} + space_left_action: {{ rhel8cis_auditd.space_left_action }} + admin_space_left_action: {{ rhel8cis_auditd.admin_space_left_action }} + max_log_file_action: {{ rhel8cis_auditd.max_log_file_action }} + +rhel8cis_logrotate: {{ rhel8cis_logrotate }} + +## Journald +# rhel8cis_journal_upload_url is the ip address to upload the journal entries to +rhel8cis_journal_upload_url: {{ rhel8cis_journal_upload_url }} +# The paths below have the default paths/files, but allow user to create custom paths/filenames +rhel8cis_journal_upload_serverkeyfile: {{ rhel8cis_journal_upload_serverkeyfile }} +rhel8cis_journal_servercertificatefile: {{ rhel8cis_journal_servercertificatefile }} +rhel8cis_journal_trustedcertificatefile: {{ rhel8cis_journal_trustedcertificatefile }} + +# The variables below related to journald, please set these to your site specific values +# rhel8cis_journald_systemmaxuse is the max amount of disk space the logs will use +rhel8cis_journald_systemmaxuse: {{ rhel8cis_journald_systemmaxuse }} +# rhel8cis_journald_systemkeepfree is the amount of disk space to keep free +rhel8cis_journald_systemkeepfree: {{ rhel8cis_journald_systemkeepfree }} +rhel8cis_journald_runtimemaxuse: {{ rhel8cis_journald_runtimemaxuse }} +rhel8cis_journald_runtimekeepfree: {{ rhel8cis_journald_runtimekeepfree }} +# rhel8cis_journald_MaxFileSec is how long in time to keep log files. Values are Xm, Xh, Xday, Xweek, Xmonth, Xyear, for example 2week is two weeks +rhel8cis_journald_maxfilesec: {{ rhel8cis_journald_maxfilesec }} + +# logrotate configuration +# change to true if you wish to change logrotate.d conf files +allow_logrotate_conf_umask_updates: {{ allow_logrotate_conf_umask_updates }} + +# The audit_back_log_limit value should never be below 8192 +rhel8cis_audit_back_log_limit: {{ rhel8cis_audit_back_log_limit }} + +# The max_log_file parameter should be based on your sites policy +rhel8cis_max_log_file_size: {{ rhel8cis_max_log_file_size }} + +## AIDE +rhel8cis_aide_scan: {{ rhel8cis_aide_scan }} +rhel8cis_config_aide: {{ rhel8cis_config_aide }} +# AIDE cron settings +rhel8cis_aide_cron: + cron_user: '{{ rhel8cis_aide_cron.cron_user }}' + cron_file: '{{ rhel8cis_aide_cron.cron_file }}' + aide_job: '{{ rhel8cis_aide_cron.aide_job }}' + aide_minute: '{{ rhel8cis_aide_cron.aide_minute }}' + aide_hour: '{{ rhel8cis_aide_cron.aide_hour }}' + aide_day: '{{ rhel8cis_aide_cron.aide_day }}' + aide_month: '{{ rhel8cis_aide_cron.aide_month }}' + aide_weekday: '{{ rhel8cis_aide_cron.aide_weekday }}' + +## Section6 vars diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 32f61f05..ae15877d 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -1,50 +1,50 @@ ## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! # This template will set all of the auditd configurations via a handler in the role in one task instead of individually -{% if rhel8cis_rule_4_1_3_1 %} +{% if rhel8cis_rule_5_2_3_1 %} -w /etc/sudoers -p wa -k scope -w /etc/sudoers.d/ -p wa -k scope {% endif %} -{% if rhel8cis_rule_4_1_3_2 %} +{% if rhel8cis_rule_5_2_3_2 %} -a always,exit -F arch=b64 -C euid!=uid -F auid!=unset -S execve -k user_emulation -a always,exit -F arch=b32 -C euid!=uid -F auid!=unset -S execve -k user_emulation {% endif %} -{% if rhel8cis_rule_4_1_3_3 %} +{% if rhel8cis_rule_5_2_3_3 %} -w {{ rhel8cis_sudolog_location }} -p wa -k sudo_log_file {% endif %} -{% if rhel8cis_rule_4_1_3_4 %} +{% if rhel8cis_rule_5_2_3_4 %} -a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time-change -a always,exit -F arch=b32 -S adjtimex,settimeofday,clock_settime -k time-change -w /etc/localtime -p wa -k time-change {% endif %} -{% if rhel8cis_rule_4_1_3_5 %} +{% if rhel8cis_rule_5_2_3_5 %} -a always,exit -F arch=b64 -S sethostname,setdomainname -F key=system-locale -a always,exit -F arch=b32 -S sethostname,setdomainname -F key=system-locale -w /etc/issue -p wa -k system-locale -w /etc/issue.net -p wa -k system-locale -w /etc/hosts -p wa -k system-locale -w /etc/sysconfig/network -p wa -k system-locale --w /etc/sysconfig/network-scripts -p wa -k system-locale +-w /etc/sysconfig/network-scripts/ -p wa -k system-locale {% endif %} -{% if rhel8cis_rule_4_1_3_6 %} +{% if rhel8cis_rule_5_2_3_6 %} {% for proc in priv_procs.stdout_lines -%} -a always,exit -F path={{ proc }} -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k privileged {% endfor %} {% endif %} -{% if rhel8cis_rule_4_1_3_7 %} +{% if rhel8cis_rule_5_2_3_7 %} -a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=access -a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=access -a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=access -a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=access {% endif %} -{% if rhel8cis_rule_4_1_3_8 %} +{% if rhel8cis_rule_5_2_3_8 %} -w /etc/group -p wa -k identity -w /etc/passwd -p wa -k identity -w /etc/gshadow -p wa -k identity -w /etc/shadow -p wa -k identity -w /etc/security/opasswd -p wa -k identity {% endif %} -{% if rhel8cis_rule_4_1_3_9 %} +{% if rhel8cis_rule_5_2_3_9 %} -a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod -a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod -a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod @@ -52,44 +52,44 @@ -a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod -a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod {% endif %} -{% if rhel8cis_rule_4_1_3_10 %} +{% if rhel8cis_rule_5_2_3_10 %} -a always,exit -F arch=b32 -S mount -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k mounts -a always,exit -F arch=b64 -S mount -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k mounts {% endif %} -{% if rhel8cis_rule_4_1_3_11 %} +{% if rhel8cis_rule_5_2_3_11 %} -w /var/run/utmp -p wa -k session -w /var/log/wtmp -p wa -k session -w /var/log/btmp -p wa -k session {% endif %} -{% if rhel8cis_rule_4_1_3_12 %} +{% if rhel8cis_rule_5_2_3_12 %} -w /var/log/lastlog -p wa -k logins -w /var/run/faillock -p wa -k logins {% endif %} -{% if rhel8cis_rule_4_1_3_13 %} --a always,exit -F arch=b64 -S rename,unlink,unlinkat,renameat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=delete --a always,exit -F arch=b32 -S rename,unlink,unlinkat,renameat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=delete +{% if rhel8cis_rule_5_2_3_13 %} +-a always,exit -F arch=b64 -S unlink,unlinkat,rename,renameat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=delete +-a always,exit -F arch=b32 -S unlink,unlinkat,rename,renameat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=delete {% endif %} -{% if rhel8cis_rule_4_1_3_14 %} +{% if rhel8cis_rule_5_2_3_14 %} -w /etc/selinux/ -p wa -k MAC-policy -w /usr/share/selinux/ -p wa -k MAC-policy {% endif %} -{% if rhel8cis_rule_4_1_3_15 %} +{% if rhel8cis_rule_5_2_3_15 %} -a always,exit -F path=/usr/bin/chcon -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k perm_chng {% endif %} -{% if rhel8cis_rule_4_1_3_16 %} +{% if rhel8cis_rule_5_2_3_16 %} -a always,exit -F path=/usr/bin/setfacl -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k perm_chng {% endif %} -{% if rhel8cis_rule_4_1_3_17 %} --a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k priv_cmd +{% if rhel8cis_rule_5_2_3_17 %} +-a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k perm_chng {% endif %} -{% if rhel8cis_rule_4_1_3_18 %} +{% if rhel8cis_rule_5_2_3_18 %} -a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k usermod {% endif %} -{% if rhel8cis_rule_4_1_3_19 %} +{% if rhel8cis_rule_5_2_3_19 %} -a always,exit -F arch=b32 -S init_module,finit_module,delete_module,create_module,query_module -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k kernel_modules -a always,exit -F arch=b64 -S init_module,finit_module,delete_module,create_module,query_module -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k kernel_modules -a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k kernel_modules {% endif %} -{% if rhel8cis_rule_4_1_3_20 %} +{% if rhel8cis_rule_5_2_3_20 %} -e 2 {% endif %} diff --git a/templates/chrony.conf.j2 b/templates/chrony.conf.j2 index 12581798..e0c31130 100644 --- a/templates/chrony.conf.j2 +++ b/templates/chrony.conf.j2 @@ -1,42 +1,95 @@ -{{ ansible_managed | comment }} +## This file is managed by Ansible, YOUR CHANGED WILL BE LOST! + +# This the default chrony.conf file for the Debian chrony package. After +# editing this file use the command 'invoke-rc.d chrony restart' to make +# your changes take effect. John Hasler 1998-2008 + +# See www.pool.ntp.org for an explanation of these servers. Please +# consider joining the project if possible. If you can't or don't want to +# use these servers I suggest that you try your ISP's nameservers. We mark +# the servers 'offline' so that chronyd won't try to connect when the link +# is down. Scripts in /etc/ppp/ip-up.d and /etc/ppp/ip-down.d use chronyc +# commands to switch it on when a dialup link comes up and off when it goes +# down. Code in /etc/init.d/chrony attempts to determine whether or not +# the link is up at boot time and set the online status accordingly. If +# you have an always-on connection such as cable omit the 'offline' +# directive and chronyd will default to online. +# +# Note that if Chrony tries to go "online" and dns lookup of the servers +# fails they will be discarded. Thus under some circumstances it is +# better to use IP numbers than host names. -# Use public servers from the pool.ntp.org project. -# Please consider joining the pool (http://www.pool.ntp.org/join.html). {% for server in rhel8cis_time_synchronization_servers -%} server {{ server }} {{ rhel8cis_chrony_server_options }} {% endfor %} -# Record the rate at which the system clock gains/losses time. -driftfile /var/lib/chrony/drift +# Look here for the admin password needed for chronyc. The initial +# password is generated by a random process at install time. You may +# change it if you wish. -# Allow the system clock to be stepped in the first three updates -# if its offset is larger than 1 second. -makestep 1.0 3 +keyfile /etc/chrony/chrony.keys -# Enable kernel synchronization of the real-time clock (RTC). -rtcsync +# Set runtime command key. Note that if you change the key (not the +# password) to anything other than 1 you will need to edit +# /etc/ppp/ip-up.d/chrony, /etc/ppp/ip-down.d/chrony, /etc/init.d/chrony +# and /etc/cron.weekly/chrony as these scripts use it to get the password. -# Enable hardware timestamping on all interfaces that support it. -#hwtimestamp * +commandkey 1 -# Increase the minimum number of selectable sources required to adjust -# the system clock. -#minsources 2 +# I moved the driftfile to /var/lib/chrony to comply with the Debian +# filesystem standard. -# Allow NTP client access from local network. -#allow 192.168.0.0/16 +driftfile /var/lib/chrony/chrony.drift -# Serve time even if not synchronized to a time source. -#local stratum 10 +# Comment this line out to turn off logging. -# Specify file containing keys for NTP authentication. -keyfile /etc/chrony.keys +log tracking measurements statistics +logdir /var/log/chrony -# Get TAI-UTC offset and leap seconds from the system tz database. -leapsectz right/UTC +# Stop bad estimates upsetting machine clock. -# Specify directory for log files. -logdir /var/log/chrony +maxupdateskew 100.0 + +# Dump measurements when daemon exits. + +dumponexit + +# Specify directory for dumping measurements. + +dumpdir /var/lib/chrony + +# Let computer be a server when it is unsynchronised. + +local stratum 10 + +# Allow computers on the unrouted nets to use the server. + +#allow 10/8 +#allow 192.168/16 +#allow 172.16/12 + +# This directive forces `chronyd' to send a message to syslog if it +# makes a system clock adjustment larger than a threshold value in seconds. + +logchange 0.5 + +# This directive defines an email address to which mail should be sent +# if chronyd applies a correction exceeding a particular threshold to the +# system clock. + +# mailonchange root@localhost 0.5 + +# This directive tells chrony to regulate the real-time clock and tells it +# Where to store related data. It may not work on some newer motherboards +# that use the HPET real-time clock. It requires enhanced real-time +# support in the kernel. I've commented it out because with certain +# combinations of motherboard and kernel it is reported to cause lockups. + +# rtcfile /var/lib/chrony/chrony.rtc -# Select which information is logged. -#log measurements statistics tracking +# If the last line of this file reads 'rtconutc' chrony will assume that +# the CMOS clock is on UTC (GMT). If it reads '# rtconutc' or is absent +# chrony will assume local time. The line (if any) was written by the +# chrony postinst based on what it found in /etc/default/rcS. You may +# change it if necessary. +rtconutc diff --git a/templates/crypto_policy_RSA.j2 b/templates/crypto_policy_RSA.j2 deleted file mode 100644 index a88f452e..00000000 --- a/templates/crypto_policy_RSA.j2 +++ /dev/null @@ -1,4 +0,0 @@ -# Enable additional options to crypto policies -# Set via ansible-lockdown project - sponsored by MindPoint Group -key_exchange = {{ rhel8cis_optional_key_exchange }} -min_rsa_size = {{ rhel8cis_optional_rsa_size }} diff --git a/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 new file mode 100644 index 00000000..03d40e81 --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 @@ -0,0 +1,6 @@ +# Added as part of RHEL8-CIS by ansible-lockdown +# Sponsored by MindPointGroup + +hash = -SHA1 +sign = -*-SHA1 +sha1_in_certs = 0 diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 new file mode 100644 index 00000000..418abe8e --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 @@ -0,0 +1,6 @@ +# Added as part of RHEL8-CIS by ansible-lockdown +# Sponsored by MindPointGroup + +# This is a subpolicy to disable all CBC mode ciphers +# for the SSH protocol (libssh and OpenSSH) +cipher@SSH = -*-CBC diff --git a/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 new file mode 100644 index 00000000..24e4c2c8 --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 @@ -0,0 +1,5 @@ +# Added as part of RHEL8-CIS by ansible-lockdown +# Sponsored by MindPointGroup + +# This is a subpolicy to disable weak macs +mac = -*-64 diff --git a/templates/etc/dconf/db/00-media-automount.j2 b/templates/etc/dconf/db/00-media-automount.j2 new file mode 100644 index 00000000..2831c6b4 --- /dev/null +++ b/templates/etc/dconf/db/00-media-automount.j2 @@ -0,0 +1,5 @@ +[org/gnome/desktop/media-handling] +automount-open=false + +[org/gnome/desktop/media-handling] +automount=false diff --git a/templates/etc/dconf/db/00-media-autorun.j2 b/templates/etc/dconf/db/00-media-autorun.j2 new file mode 100644 index 00000000..85f8bf5a --- /dev/null +++ b/templates/etc/dconf/db/00-media-autorun.j2 @@ -0,0 +1,2 @@ +[org/gnome/desktop/media-handling] +autorun-never=true diff --git a/templates/etc/dconf/db/00-screensaver.j2 b/templates/etc/dconf/db/00-screensaver.j2 new file mode 100644 index 00000000..e28f12a8 --- /dev/null +++ b/templates/etc/dconf/db/00-screensaver.j2 @@ -0,0 +1,9 @@ +[org/gnome/desktop/session] +# Number of seconds of inactivity before the screen goes blank +# Set to 0 seconds if you want to deactivate the screensaver. +idle-delay=uint32 {{ rhel8cis_screensaver_idle_delay }} + +# Specify the dconf path +[org/gnome/desktop/screensaver] +# Number of seconds after the screen is blank before locking the screen +lock-delay=uint32 {{ rhel8cis_screensaver_lock_delay }} diff --git a/templates/etc/dconf/db/locks/00-automount_lock.j2 b/templates/etc/dconf/db/locks/00-automount_lock.j2 new file mode 100644 index 00000000..0e8e193c --- /dev/null +++ b/templates/etc/dconf/db/locks/00-automount_lock.j2 @@ -0,0 +1,6 @@ +# Lock automount settings + +# Lock desktop media-handling automount setting +/org/gnome/desktop/media-handling/automount +# Lock desktop media-handling automount-open setting +/org/gnome/desktop/media-handling/automount-open diff --git a/templates/etc/dconf/db/locks/00-autorun_lock.j2 b/templates/etc/dconf/db/locks/00-autorun_lock.j2 new file mode 100644 index 00000000..1be853de --- /dev/null +++ b/templates/etc/dconf/db/locks/00-autorun_lock.j2 @@ -0,0 +1,3 @@ +# Lock desktop media-handling settings +# Lock desktop media-handling autorun-never setting +/org/gnome/desktop/media-handling/autorun-never diff --git a/templates/etc/dconf/db/locks/00-screensaver_lock.j2 b/templates/etc/dconf/db/locks/00-screensaver_lock.j2 new file mode 100644 index 00000000..c1e0cbe1 --- /dev/null +++ b/templates/etc/dconf/db/locks/00-screensaver_lock.j2 @@ -0,0 +1,4 @@ +# Lock desktop screensaver idle-delay setting +/org/gnome/desktop/session/idle-delay +# Lock desktop screensaver lock-delay setting +/org/gnome/desktop/screensaver/lock-delay diff --git a/templates/etc/systemd/system/tmp.mount.j2 b/templates/etc/systemd/system/tmp.mount.j2 index 6bfcd6a9..2e3a1896 100644 --- a/templates/etc/systemd/system/tmp.mount.j2 +++ b/templates/etc/systemd/system/tmp.mount.j2 @@ -1,4 +1,4 @@ -{{ ansible_managed | comment }} +## This file is managed by Ansible, YOUR CHANGED WILL BE LOST! # SPDX-License-Identifier: LGPL-2.1+ # diff --git a/templates/ntp.conf.j2 b/templates/ntp.conf.j2 index 34fe555f..1fc240a3 100644 --- a/templates/ntp.conf.j2 +++ b/templates/ntp.conf.j2 @@ -1,4 +1,4 @@ -{{ ansible_managed | comment }} +## This file is managed by Ansible, YOUR CHANGED WILL BE LOST! # For more information about this file, see the man pages # ntp.conf(5), ntp_acc(5), ntp_auth(5), ntp_clock(5), ntp_misc(5), ntp_mon(5). diff --git a/vars/audit.yml b/vars/audit.yml index c7471f35..250a600e 100644 --- a/vars/audit.yml +++ b/vars/audit.yml @@ -10,11 +10,22 @@ audit_cmd_timeout: 120000 # if get_audit_binary_method == download change accordingly audit_bin_url: "https://github.com/goss-org/goss/releases/download/{{ audit_bin_version.release }}/goss-linux-" +## if get_audit_binary_method - copy the following needs to be updated for your environment +## it is expected that it will be copied from somewhere accessible to the control node +## e.g copy from ansible control node to remote host +audit_bin_copy_location: /some/accessible/path + ### Goss Audit Benchmark file ### ## managed by the control audit_content # git audit_file_git: "https://github.com/ansible-lockdown/{{ benchmark }}-Audit.git" -audit_git_version: "benchmark_{{ benchmark_version }}_rh8" +audit_git_version: "benchmark_{{ benchmark_version }}" + +# archive or copy: +audit_conf_copy: "some path to copy from" + +# get_url: +audit_files_url: "some url maybe s3?" ## Goss configuration information # Where the goss configs and outputs are stored @@ -30,8 +41,8 @@ post_audit_outfile: "{{ audit_out_dir }}/{{ ansible_facts.hostname }}-{{ benchma ### Audit binary settings ### audit_bin_version: - release: v0.3.23 - AMD64_checksum: 'sha256:9e9f24e25f86d6adf2e669a9ffbe8c3d7b9b439f5f877500dea02ba837e10e4d' + release: v0.4.4 + AMD64_checksum: 'sha256:1c4f54b22fde9d4d5687939abc2606b0660a5d14a98afcd09b04b793d69acdc5' audit_bin_path: /usr/local/bin/ audit_bin: "{{ audit_bin_path }}goss" audit_format: json diff --git a/vars/main.yml b/vars/main.yml index 9868ccb1..e0d92405 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -6,7 +6,6 @@ rhel8cis_allowed_crypto_policies: - 'DEFAULT' - 'FUTURE' - 'FIPS' -rhel8cis_crypto_override: false rhel8cis_allowed_crypto_policies_modules: - 'OSPP' @@ -14,7 +13,9 @@ rhel8cis_allowed_crypto_policies_modules: # default setting, this should not be changed # and is overridden if a task that changed sets the value if required. -change_requires_reboot: false +reboot_required: false + +rhel8cis_legacy_boot: false # Used to control warning summary warn_control_list: "" From b1aa190686c0b45b8ca2822625a04f429182d158 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 11 Mar 2024 13:10:02 +0000 Subject: [PATCH 02/62] updated Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.4.2.x.yml | 4 ++-- templates/ansible_vars_goss.yml.j2 | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tasks/section_4/cis_4.4.2.x.yml b/tasks/section_4/cis_4.4.2.x.yml index 8fe19004..e7e64cee 100644 --- a/tasks/section_4/cis_4.4.2.x.yml +++ b/tasks/section_4/cis_4.4.2.x.yml @@ -16,8 +16,8 @@ block: - name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used | Create custom profiles" when: - - "rhel8cis_authselect['custom_profile_name'] not in authselect_running_config.stdout" - rhel8cis_authselect_custom_profile_create + - authselect_running_config.stdout is not defined - not rhel8cis_4_4_2_1_profile.stat.exists ansible.builtin.shell: "/usr/bin/authselect create-profile {{ rhel8cis_authselect['custom_profile_name'] }} -b {{ rhel8cis_authselect['default_file_to_copy'] }}" args: @@ -25,8 +25,8 @@ - name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used | Select profiles" when: - - "rhel8cis_authselect['custom_profile_name'] not in authselect_running_config.stdout" - rhel8cis_authselect_custom_profile_select + - (authselect_running_config.stdout is defined and "rhel8cis_authselect['custom_profile_name'] not in authselect_running_config.stdout") ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel8cis_authselect['custom_profile_name'] }}{% if rhel8cis_rule_4_4_2_2 %} with-faillock{% endif %}{% if rhel8cis_rule_4_4_2_4 %} with-pwhistory{% endif %}{% if rhel8cis_rule_4_4_3_4_1 %} without-nullok{% endif %} --force" - name: "4.4.2.2 | PATCH | Ensure pam_faillock module is enabled" diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index fd5a4821..dd87431c 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -443,7 +443,7 @@ rhel8cis_set_boot_pass: {{ rhel8cis_set_boot_pass }} rhel8cis_boot_path: {{ rhel8cis_boot_path }} # 1.5 SELinux policy -rhel8cis_selinux_pol: {{ rhel8cis_selinux_pol }} +rhel8cis_selinux_pol: {{ rhel8cis_selinux_policy }} # 1.6 Set crypto policy (LEGACY, DEFAULT, FUTURE, FIPS) rhel8cis_crypto_policy: {{ rhel8cis_crypto_policy }} From 70e7479bd7adf6136b52dc14061e709428caad23 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 11 Mar 2024 13:23:16 +0000 Subject: [PATCH 03/62] removed old conflict line Signed-off-by: Mark Bolwell --- Changelog.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index b3274ef3..e46e3c0e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -171,10 +171,6 @@ Issues. - #228 Thanks to benbulll - audit binary copy var missing -<<<<<<< HEAD -======= - ->>>>>>> devel ## 1.4.0 - workflow improvements From a0bba55cc76596acd906bd25f00775acd5b0b443 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 11 Mar 2024 15:08:34 +0000 Subject: [PATCH 04/62] tidy up warning on 432 Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index e33743d6..201012eb 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -420,7 +420,7 @@ when: rhel8cis_6_1_14_packages_rpm.stdout | length > 0 ansible.builtin.debug: msg: | - "Warning!! You have some package descrepancies issues. + "Warning!! We have discovered package discrepancies. The file list can be found in {{ rhel8cis_rpm_audit_file }}" - name: "6.1.14 | AUDIT | Audit system file permissions | Warn Count" From 895ea43f5bd37014fb833fd98a43ca180db734ac Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 11 Mar 2024 15:09:05 +0000 Subject: [PATCH 05/62] tidy up ec2_checks Signed-off-by: Mark Bolwell --- tasks/main.yml | 1 - tasks/section_1/cis_1.6.x.yml | 4 ---- tasks/section_5/cis_5.3.x.yml | 2 -- 3 files changed, 7 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index f4e84a6a..75da3253 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -4,7 +4,6 @@ - name: Check OS version and family when: - os_check - - not system_is_ec2 tags: - always ansible.builtin.assert: diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml index 604c03e9..5f672ee0 100644 --- a/tasks/section_1/cis_1.6.x.yml +++ b/tasks/section_1/cis_1.6.x.yml @@ -7,7 +7,6 @@ - level1-server - level1-workstation - automated - - no system_is_ec2 - patch - NIST800-53R5_SC-8 - rule_1.6.1 @@ -32,7 +31,6 @@ - level1-server - level1-workstation - automated - - no system_is_ec2 - patch - NIST800-53R5_SC-8 - rule_1.6.2 @@ -54,7 +52,6 @@ - level1-server - level1-workstation - automated - - no system_is_ec2 - patch - NIST800-53R5_SC-8 - rule_1.6.3 @@ -76,7 +73,6 @@ - level1-server - level1-workstation - automated - - no system_is_ec2 - patch - NIST800-53R5_SC-8 - rule_1.6.4 diff --git a/tasks/section_5/cis_5.3.x.yml b/tasks/section_5/cis_5.3.x.yml index e42be413..754f57b4 100644 --- a/tasks/section_5/cis_5.3.x.yml +++ b/tasks/section_5/cis_5.3.x.yml @@ -38,7 +38,6 @@ when: - rhel8cis_rule_5_3_2 - rhel8cis_config_aide - - not system_is_ec2 tags: - level1-server - level1-workstation @@ -75,7 +74,6 @@ - name: "5.3.3 | Ensure cryptographic mechanisms are used to protect the integrity of audit tools" when: - rhel8cis_rule_5_3_3 - - not system_is_ec2 tags: - level1-server - level1-workstation From 670a0b00c1989abb0167f7ac7eb28f22e23a9bfb Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 11 Mar 2024 15:11:12 +0000 Subject: [PATCH 06/62] updated warning on line 435 Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.2.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_6/cis_6.2.x.yml b/tasks/section_6/cis_6.2.x.yml index 311bc49e..ffecad2f 100644 --- a/tasks/section_6/cis_6.2.x.yml +++ b/tasks/section_6/cis_6.2.x.yml @@ -432,7 +432,7 @@ ansible.builtin.debug: msg: - - "Warning!! You have group or world-writable dot files on your system and have configured for manual intervention" + - "Warning!! We have discovered group or world-writable dot files on your system and this host is configured for manual intervention. Please investigate these files further." - name: "6.2.11 | PATCH | Ensure local interactive user dot files access is configured | Set warning count" when: From a14197818b2976898d6ff30d5a37951c2883c882 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 12 Mar 2024 15:49:48 +0000 Subject: [PATCH 07/62] updated prelim and typos Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 40 ++++++++++++++++++++++++++++++++++++++++ tasks/section_5/main.yml | 4 ++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index abd4d21a..a1c28329 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -275,6 +275,46 @@ name: audit state: present +- name: "PRELIM | 5.2.4.x | Ensure audit log files are mode 0640 or less permissive | discover file" + ansible.builtin.shell: "grep ^log_file /etc/audit/auditd.conf | awk '{ print $NF }'" + changed_when: false + failed_when: audit_discovered_logfile.rc not in [0, 1] + register: audit_discovered_logfile + when: + - rhel8cis_rule_5_2_4_1 + - rhel8cis_rule_5_2_4_2 + - rhel8cis_rule_5_2_4_3 + - rhel8cis_rule_5_2_4_4 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.1 + - rule_5.2.4.2 + - rule_5.2.4.3 + - rule_5.2.4.4 + +- name: "PRELIM | 5.2.4.5/6/7 | Audit conf and rules files | list files" + ansible.builtin.find: + path: /etc/audit + file_type: file + recurse: true + patterns: '*.conf,*.rules' + register: auditd_conf_files + when: + - rhel8cis_rule_5_2_4_5 or + rhel8cis_rule_5_2_4_6 or + rhel8cis_rule_5_2_4_7 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.5 + - rule_5.2.4.6 + - rule_5.2.4.7 + - name: "PRELIM | Gather accounts with empty password fields" when: - rhel8cis_rule_6_2_1 diff --git a/tasks/section_5/main.yml b/tasks/section_5/main.yml index 74c518bf..bb681227 100644 --- a/tasks/section_5/main.yml +++ b/tasks/section_5/main.yml @@ -35,9 +35,9 @@ ansible.builtin.import_tasks: file: cis_5.2.3.x.yml -- name: "SECTION | 5.2.3.x | Audit file permissions" +- name: "SECTION | 5.2.4.x | Audit file permissions" ansible.builtin.import_tasks: - file: cis_5.2.3.x.yml + file: cis_5.2.4.x.yml - name: "SECTION | 5.3.x | Aide" ansible.builtin.import_tasks: From d587aeee6b0d555459c10dbee54ecfa81b708eb0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 17:48:25 +0000 Subject: [PATCH 08/62] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v24.2.0 → v24.2.1](https://github.com/ansible-community/ansible-lint/compare/v24.2.0...v24.2.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0368cf3e..45d1df9c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -44,7 +44,7 @@ repos: exclude: .config/.secrets.baseline - repo: https://github.com/ansible-community/ansible-lint - rev: v24.2.0 + rev: v24.2.1 hooks: - id: ansible-lint name: Ansible-lint From 319a091ba82901eb171a646beca327b2a32d6cb2 Mon Sep 17 00:00:00 2001 From: uk-bolly Date: Wed, 20 Mar 2024 13:08:47 +0000 Subject: [PATCH 09/62] March 24 updates (#356) * added conditional to user password check #354 thanks to @bbaassssiiee Signed-off-by: Mark Bolwell * updated logic to check root passwd locked Signed-off-by: Mark Bolwell * Updated Signed-off-by: Mark Bolwell * lint and audit order change Signed-off-by: Mark Bolwell * updated for documentation format Signed-off-by: Mark Bolwell --------- Signed-off-by: Mark Bolwell --- Changelog.md | 11 +++ defaults/main.yml | 2 +- tasks/audit_only.yml | 4 +- tasks/main.yml | 24 +----- tasks/post_remediation_audit.yml | 10 +-- tasks/pre_remediation_audit.yml | 2 +- tasks/prelim.yml | 125 ++++++++++++++++++------------- 7 files changed, 95 insertions(+), 83 deletions(-) diff --git a/Changelog.md b/Changelog.md index e46e3c0e..2df2a612 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,17 @@ ### This is not an upgrade for CIS v2.0.0 due to the number of changes treat as a new baseline +### Changes and improvements (March24) + +thanks to @bbaassssiiee + +- #353 +- #354 + +Audit and audit_only changed to run prior to any significant changes + +#### Initial + Inline with new CIS baseline Rewrite and ordering of nearly all controls Many new controls added diff --git a/defaults/main.yml b/defaults/main.yml index 724cbe4a..73cf243e 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -492,7 +492,7 @@ rhel8cis_selinux_policy: targeted # 1.6 Set crypto policy (LEGACY, DEFAULT, FUTURE, FIPS) rhel8cis_crypto_policy: 'DEFAULT' -# Added module to be allowed as default setting (Allowed options in vars/main.yml) +# Added module to be loaded - (Allowed options in vars/main.yml - OSPP and AD-SUPPORT) rhel8cis_crypto_policy_module: '' # 1.7 diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index 864f5bbe..f267a1e7 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -1,22 +1,22 @@ --- - name: Audit_Only | Create local Directories for hosts + when: fetch_audit_files ansible.builtin.file: mode: '0755' path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}" recurse: true state: directory - when: fetch_audit_files delegate_to: localhost become: false - name: Audit_only | Get audits from systems and put in group dir + when: fetch_audit_files ansible.builtin.fetch: dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/" flat: true mode: '0644' src: "{{ pre_audit_outfile }}" - when: fetch_audit_files - name: Audit_only | Show Audit Summary when: diff --git a/tasks/main.yml b/tasks/main.yml index 75da3253..e6a37976 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -53,7 +53,7 @@ - always block: - name: Ensure root password is set - ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)" + ansible.builtin.shell: passwd -S root | grep -E "(Password set, SHA512 crypt|Password locked|root\s(LK|L)\s)" changed_when: false failed_when: false register: root_passwd_set @@ -91,6 +91,7 @@ - ansible_env.SUDO_USER is defined - not system_is_ec2 - not audit_only + - rhel8cis_rule_4_3_4 block: - name: Capture current password state of connecting user" ansible.builtin.shell: "grep {{ ansible_env.SUDO_USER }} /etc/shadow | awk -F: '{print $2}'" @@ -105,7 +106,7 @@ fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} has no password set - It can break access" success_msg: "You have a password set for the {{ ansible_env.SUDO_USER }} user" vars: - sudo_password_rule: rhel8cis_rule_5_3_4 # pragma: allowlist secret + sudo_password_rule: rhel8cis_rule_4_3_4 # pragma: allowlist secret - name: Include prelim tasks tags: @@ -114,25 +115,6 @@ ansible.builtin.import_tasks: file: prelim.yml -- name: Include audit specific variables - when: - - run_audit or audit_only - - setup_audit - tags: - - setup_audit - - run_audit - ansible.builtin.include_vars: - file: audit.yml - -- name: Include pre-remediation audit tasks - when: - - run_audit or audit_only - - setup_audit - tags: - - run_audit - ansible.builtin.import_tasks: - file: pre_remediation_audit.yml - - name: Gather the package facts after prelim tags: - always diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index eb01bc75..64eb6f5f 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -1,14 +1,14 @@ --- - name: Post Audit | Run post_remediation {{ benchmark }} audit - ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ post_audit_outfile }} -g {{ group_names }}" + ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g {{ group_names }}" changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" AUDIT_CONTENT_LOCATION: "{{ audit_out_dir }}" AUDIT_FILE: goss.yml -- name: Post Audit | ensure audit files readable by users +- name: Post Audit | Ensure audit files readable by users ansible.builtin.file: path: "{{ item }}" mode: '0644' @@ -21,12 +21,12 @@ when: - audit_format == "json" block: - - name: capture data {{ post_audit_outfile }} + - name: Post Audit | Capture data {{ post_audit_outfile }} ansible.builtin.shell: cat {{ post_audit_outfile }} register: post_audit changed_when: false - - name: Capture post-audit result + - name: Post Audit | Capture post-audit result ansible.builtin.set_fact: post_audit_summary: "{{ post_audit.stdout | from_json | json_query(summary) }}" vars: @@ -36,7 +36,7 @@ when: - audit_format == "documentation" block: - - name: Post Audit | capture data {{ post_audit_outfile }} + - name: Post Audit | Capture data {{ post_audit_outfile }} ansible.builtin.shell: tail -2 {{ post_audit_outfile }} register: post_audit changed_when: false diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 5f2560e4..4ab3e4ac 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -77,7 +77,7 @@ mode: '0600' - name: Pre Audit | Run pre_remediation {{ benchmark }} audit - ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ pre_audit_outfile }} -g {{ group_names }}" + ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g {{ group_names }}" changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" diff --git a/tasks/prelim.yml b/tasks/prelim.yml index a1c28329..eb8a2b9d 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -1,7 +1,7 @@ --- # Preliminary tasks that should always be run -- name: "PRELIM | Add the required packages" +- name: "PRELIM | PATCH | Add the required packages" tags: - always ansible.builtin.package: @@ -11,7 +11,7 @@ state: present # List users in order to look files inside each home directory -- name: "PRELIM | List users accounts" +- name: "PRELIM | AUDIT | List users accounts" tags: - always ansible.builtin.shell: "awk -F: '{print $1}' /etc/passwd" @@ -19,73 +19,92 @@ check_mode: false register: users -- name: "PRELIM | Gather interactive user ID min and max" +- name: "PRELIM | AUDIT | Gather interactive user ID min and max" when: - rhel8uid_info_dynamic tags: - always block: - - name: "PRELIM | Gather interactive user ID min" + - name: "PRELIM | AUDIT | Gather interactive user ID min" ansible.builtin.shell: grep ^UID_MIN /etc/login.defs | awk '{print $2}' changed_when: false failed_when: false register: rhel8cis_min_uid - - name: "PRELIM | Gather interactive user ID max" + - name: "PRELIM | AUDIT | Gather interactive user ID max" ansible.builtin.shell: grep ^UID_MAX /etc/login.defs | awk '{print $2}' changed_when: false failed_when: false register: rhel8cis_max_uid - - name: "PRELIM | Setting the fact" + - name: "PRELIM | AUDIT | Setting the fact" ansible.builtin.set_fact: rhel8uid_interactive_uid_start: "{{ rhel8cis_min_uid.stdout | string }}" rhel8uid_interactive_uid_stop: "{{ rhel8cis_max_uid.stdout | string }}" -- name: "PRELIM | Set facts based on boot type" +- name: "PRELIM | AUDIT | Set facts based on boot type" tags: - always block: - - name: "PRELIM | Check whether machine is UEFI-based" + - name: "PRELIM | AUDIT | Check whether machine is UEFI-based" ansible.builtin.stat: path: /sys/firmware/efi register: rhel_08_efi_boot - - name: "PRELIM | set legacy boot and grub path | Bios" + - name: "PRELIM | AUDIT | set legacy boot and grub path fact | Bios" + when: not rhel_08_efi_boot.stat.exists ansible.builtin.set_fact: rhel8cis_legacy_boot: true grub2_path: /etc/grub2.cfg rhel8cis_boot_path: /boot/grub2/ - when: not rhel_08_efi_boot.stat.exists - - name: "PRELIM | set grub fact | UEFI" + - name: "PRELIM | AUDIT | set grub fact | UEFI" + when: rhel_08_efi_boot.stat.exists ansible.builtin.set_fact: grub2_path: /etc/grub2-efi.cfg rhel8cis_boot_path: "/boot/efi/EFI/{{ansible_facts.distribution | lower }}/" - when: rhel_08_efi_boot.stat.exists - name: "PRELIM | AUDIT | Ensure permissions on bootloader config are configured | Get grub config file stats" + tags: + - always ansible.builtin.stat: path: "{{ grub2_path }}" changed_when: false register: grub_cfg - tags: - - always -- name: "PRELIM | Gather the package facts before prelim" +- name: "PRELIM | AUDIT | Gather the package facts before prelim" tags: - always ansible.builtin.package_facts: manager: auto +- name: Include audit specific variables + when: + - run_audit or audit_only + - setup_audit + tags: + - setup_audit + - run_audit + ansible.builtin.include_vars: + file: audit.yml + +- name: Include pre-remediation audit tasks + when: + - run_audit or audit_only + - setup_audit + tags: + - run_audit + ansible.builtin.import_tasks: + file: pre_remediation_audit.yml + ##### Section requirements ##### -- name: "PRELIM | Section 1.1 | Create list of mount points" +- name: "PRELIM | AUDIT | Section 1.1 | Create list of mount points" tags: - always ansible.builtin.set_fact: mount_names: "{{ ansible_mounts | map(attribute='mount') | list }}" -- name: "PRELIM | Ensure /dev/shm is a separate partition | discover" +- name: "PRELIM | AUDIT | Ensure /dev/shm is a separate partition | discover" when: - rhel8cis_rule_1_1_2_2_1 or rhel8cis_rule_1_1_2_2_2 or @@ -98,7 +117,7 @@ failed_when: rhel8cis_dev_shm_present.rc not in [ 0, 1 ] register: rhel8cis_dev_shm_present -- name: "PRELIM | if systemd coredump" +- name: "PRELIM | AUDIT | systemd coredump file check" when: - rhel8cis_rule_1_4_4 tags: @@ -107,33 +126,33 @@ path: /etc/systemd/coredump.conf register: systemd_coredump -- name: "PRELIM | Ensure crypto-policies-scripts package is installed" +- name: "PRELIM | AUDIT | Ensure crypto-policies-scripts package is installed" tags: - always ansible.builtin.package: name: crypto-policies-scripts state: installed -- name: "PRELIM | Gather system-wide crypto-policy settings" +- name: "PRELIM | AUDIT | Gather system-wide crypto-policy settings" tags: - always block: - - name: "PRELIM | Gather system-wide crypto-policy settings" + - name: "PRELIM | AUDIT | Gather system-wide crypto-policy settings" ansible.builtin.shell: 'update-crypto-policies --show' changed_when: false check_mode: false register: rhel8cis_system_wide_crypto_policy - - name: "PRELIM | Gather system-wide crypto-policy | set fact for crypto policy" + - name: "PRELIM | AUDIT | Gather system-wide crypto-policy | set fact for crypto policy" ansible.builtin.set_fact: current_crypto_policy: "{{ rhel8cis_system_wide_crypto_policy.stdout.split(':')[0] }}" - - name: "PRELIM | Gather system-wide crypto-policy module | set fact for crypto submodule" + - name: "PRELIM | AUDIT | Gather system-wide crypto-policy module | set fact for crypto submodule" + when: "':' in rhel8cis_system_wide_crypto_policy.stdout" ansible.builtin.set_fact: current_crypto_module: "{{ rhel8cis_system_wide_crypto_policy.stdout.split(':')[1] }}" - when: "':' in rhel8cis_system_wide_crypto_policy.stdout" -- name: "PRELIM | Install dconf if gui" +- name: "PRELIM | PATCH | Install dconf if gui" when: - "'gdm' in ansible_facts.packages" - "'dconf' not in ansible_facts.packages" @@ -144,14 +163,14 @@ name: dconf state: present -- name: "PRELIM | Cron Package" +- name: "PRELIM | PATCH | Cron Package" tags: - always ansible.builtin.package: name: cronie state: present -- name: "PRELIM | Find all sudoers files." +- name: "PRELIM | AUDIT | Find all sudoers files." when: - rhel8cis_rule_4_3_4 or rhel8cis_rule_4_3_5 @@ -163,7 +182,7 @@ check_mode: false register: rhel8cis_sudoers_files -- name: "PRELIM | Check authselect package versions" +- name: "PRELIM | AUDIT | Check authselect package versions" tags: - always - authselect @@ -171,22 +190,22 @@ warn_control_id: 'authselect_pkg_version_too_low' authselect_pkg_version: 1.2.6 block: - - name: "PRELIM | Check authselect package versions | set fact" + - name: "PRELIM | AUDIT | Check authselect package versions | set fact" when: ansible_facts.packages.authselect[0].version is version(authselect_pkg_version, '>=') ansible.builtin.set_fact: authselect_version: OK - - name: "PRELIM | Check authselect package versions | Warning" + - name: "PRELIM | WARN | Check authselect package versions | Warning" when: ansible_facts.packages.authselect[0].version is version(authselect_pkg_version, '<') ansible.builtin.debug: msg: "Warning!! Authselect controls won't run as authselect pkg version too low" - - name: "PRELIM | Check authselect package versions | Warning" + - name: "PRELIM | WARN | Check authselect package versions | Warning" when: ansible_facts.packages.authselect[0].version is version(authselect_pkg_version, '<') ansible.builtin.import_tasks: file: warning_facts.yml -- name: "PRELIM | Check pam package versions" +- name: "PRELIM | AUDIT | Check pam package versions" tags: - always vars: @@ -194,28 +213,28 @@ pam_pkg_version: 1.3.1 pam_pkg_release: 25 block: - - name: "PRELIM | Check pam package versions | set fact" + - name: "PRELIM | AUDIT | Check pam package versions | set fact" when: - ansible_facts.packages.pam[0].version is version(pam_pkg_version, '>=') - ansible_facts.packages.pam[0].release is version (pam_pkg_release, '>=') ansible.builtin.set_fact: pam_version: OK - - name: "PRELIM | Check pam package versions | Warning" + - name: "PRELIM | WARN | Check pam package versions | Warning" when: - ansible_facts.packages.pam[0].version is version(pam_pkg_version, '<') - ansible_facts.packages.pam[0].release is version (pam_pkg_release, '<') ansible.builtin.debug: msg: "Warning!! Authselect controls won't run as pam package version too low" - - name: "PRELIM | Check pam package versions | Warning" + - name: "PRELIM | WARN | Check pam package versions | Warning" when: - ansible_facts.packages.pam[0].version is version(pam_pkg_version, '<') - ansible_facts.packages.pam[0].release is version (pam_pkg_release, '<') ansible.builtin.import_tasks: file: warning_facts.yml -- name: "PRELIM | Check authselect profile is selected" +- name: "PRELIM | AUDIT | Check authselect profile is selected" when: - rhel8cis_allow_authselect_updates - rhel8cis_rule_4_4_2_1 or @@ -229,37 +248,37 @@ tags: - always block: - - name: "PRELIM | Check authselect profile name has been updated" + - name: "PRELIM | AUDIT | Check authselect profile name has been updated" ansible.builtin.assert: that: rhel8cis_authselect['custom_profile_name'] != 'cis_example_profile' fail_msg: "You still have the default name for your authselect profile" - - name: "PRELIM | Check authselect profile is selected" + - name: "PRELIM | AUDIT | Check authselect profile is selected" when: not rhel8cis_authselect_custom_profile_create ansible.builtin.shell: authselect current changed_when: false failed_when: authselect_running_config.rc not in [ 0, 1 ] register: authselect_running_config - - name: "PRELIM | Check authselect profile is selected" + - name: "PRELIM | AUDIT | Check authselect profile is selected" ansible.builtin.assert: that: not rhel8cis_authselect_custom_profile_create and "'example' not in rhel8cis_authselect['custom_profile_name']" or authselect_running_config is defined success_msg: "Authselect is running and profile is selected" fail_msg: Authselect updates have been selected there are issues with profile selection" - - name: "PRELIM | Check profile exists if not created" + - name: "PRELIM | AUDIT | Check profile exists if not created" ansible.builtin.stat: path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}" register: rhel8cis_4_4_2_1_profile - - name: "PRELIM | Check authselect profile exists if not created" + - name: "PRELIM | AUDIT | Check authselect profile exists if not created" when: rhel8cis_4_4_2_1_profile.stat.exists ansible.builtin.assert: that: not rhel8cis_authselect_custom_profile_create success_msg: "Authselect is running and profile is selected" fail_msg: Authselect updates have been selected but you have stated create and profile already exists" -- name: "PRELIM | Interactive User accounts home directories" +- name: "PRELIM | AUDIT | Interactive User accounts home directories" tags: - always ansible.builtin.shell: > @@ -267,7 +286,7 @@ changed_when: false register: interactive_users_home -- name: "PRELIM | Section 5.1 | Configure System Accounting (auditd)" +- name: "PRELIM | PATCH | Section 5.1 | Configure System Accounting (auditd)" when: rhel8cis_level_2 tags: - always @@ -275,7 +294,7 @@ name: audit state: present -- name: "PRELIM | 5.2.4.x | Ensure audit log files are mode 0640 or less permissive | discover file" +- name: "PRELIM | AUDIT | 5.2.4.x | Ensure audit log files are mode 0640 or less permissive | discover file" ansible.builtin.shell: "grep ^log_file /etc/audit/auditd.conf | awk '{ print $NF }'" changed_when: false failed_when: audit_discovered_logfile.rc not in [0, 1] @@ -295,13 +314,7 @@ - rule_5.2.4.3 - rule_5.2.4.4 -- name: "PRELIM | 5.2.4.5/6/7 | Audit conf and rules files | list files" - ansible.builtin.find: - path: /etc/audit - file_type: file - recurse: true - patterns: '*.conf,*.rules' - register: auditd_conf_files +- name: "PRELIM | AUDIT | 5.2.4.5/6/7 | Audit conf and rules files | list files" when: - rhel8cis_rule_5_2_4_5 or rhel8cis_rule_5_2_4_6 or @@ -314,8 +327,14 @@ - rule_5.2.4.5 - rule_5.2.4.6 - rule_5.2.4.7 + ansible.builtin.find: + path: /etc/audit + file_type: file + recurse: true + patterns: '*.conf,*.rules' + register: auditd_conf_files -- name: "PRELIM | Gather accounts with empty password fields" +- name: "PRELIM | AUDIT | Gather accounts with empty password fields" when: - rhel8cis_rule_6_2_1 tags: @@ -325,7 +344,7 @@ check_mode: false register: empty_password_accounts -- name: "PRELIM | Gather UID 0 accounts other than root" +- name: "PRELIM | AUDIT | Gather UID 0 accounts other than root" when: - rhel8cis_rule_6_2_8 tags: From 4d0dabaf36ed92a423bb779c1230ff1a8b21330c Mon Sep 17 00:00:00 2001 From: Bas Date: Thu, 21 Mar 2024 10:09:17 +0100 Subject: [PATCH 10/62] Allow for a local site policy for the openSSH server. (#358) If changes to the system-wide crypto policy are required to meet local site policy for the openSSH server, these changes should be done with a sub-policy assigned to the system-wide crypto policy. The role defaults can be overridden by the user's vars. The user should implement a .pmod file, and add its basename to `rhel8cis_allowed_crypto_policies_modules`. The role vars are harder to change due to the 21 priority levels of Ansible. Signed-off-by: Bas Meijer --- defaults/main.yml | 9 ++++++++- vars/main.yml | 4 ---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 73cf243e..da0cb0e1 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -492,7 +492,14 @@ rhel8cis_selinux_policy: targeted # 1.6 Set crypto policy (LEGACY, DEFAULT, FUTURE, FIPS) rhel8cis_crypto_policy: 'DEFAULT' -# Added module to be loaded - (Allowed options in vars/main.yml - OSPP and AD-SUPPORT) + +# 1.6.1 Allowed crypto-policy modules +rhel8cis_allowed_crypto_policies_modules: + - 'AD-SUPPORT' + - 'NO-SHA1' + - 'OSPP' + +# Added module to be loaded rhel8cis_crypto_policy_module: '' # 1.7 diff --git a/vars/main.yml b/vars/main.yml index e0d92405..9a92b432 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -7,10 +7,6 @@ rhel8cis_allowed_crypto_policies: - 'FUTURE' - 'FIPS' -rhel8cis_allowed_crypto_policies_modules: - - 'OSPP' - - 'AD-SUPPORT' - # default setting, this should not be changed # and is overridden if a task that changed sets the value if required. reboot_required: false From 59dcd8fba2413dcdb0d51830e74cd2c0e001a92f Mon Sep 17 00:00:00 2001 From: uk-bolly Date: Wed, 27 Mar 2024 15:44:15 +0000 Subject: [PATCH 11/62] Issues March24 (#366) * #359 addressed thanks to @bbaassssiiee Signed-off-by: Mark Bolwell * sysctl matches requirement & handler added Signed-off-by: Mark Bolwell * container updated and cautions updated Signed-off-by: Mark Bolwell * issues #360 addressed thanks to @bbaassssiiee Signed-off-by: Mark Bolwell * updated Signed-off-by: Mark Bolwell * Added #361 ensure local interface on 3.4.2.2 Signed-off-by: Mark Bolwell * issue #363 addressed Signed-off-by: Mark Bolwell * variable naming and lint Signed-off-by: Mark Bolwell * variable naming and lint Signed-off-by: Mark Bolwell * updated handler Signed-off-by: Mark Bolwell * variable naming and lint updates Signed-off-by: Mark Bolwell * updated Signed-off-by: Mark Bolwell * fix issues with pam_unix Signed-off-by: Mark Bolwell * added extra options Signed-off-by: Mark Bolwell * issue #365 addressed Signed-off-by: Mark Bolwell * fixed commenting alternate file Signed-off-by: Mark Bolwell * updated var name to discovered Signed-off-by: Mark Bolwell * renamed variable tomake it clearer Signed-off-by: Mark Bolwell * updated Signed-off-by: Mark Bolwell * fix typo Signed-off-by: Mark Bolwell * updated discovered variable naming Signed-off-by: Mark Bolwell * updated variable naming Signed-off-by: Mark Bolwell --------- Signed-off-by: Mark Bolwell --- Changelog.md | 9 + README.md | 14 +- defaults/main.yml | 4 +- handlers/main.yml | 9 +- tasks/auditd.yml | 5 +- tasks/main.yml | 8 +- tasks/parse_etc_password.yml | 6 +- tasks/post_remediation_audit.yml | 10 +- tasks/pre_remediation_audit.yml | 18 +- tasks/prelim.yml | 92 +++--- tasks/section_1/cis_1.1.1.x.yml | 6 +- tasks/section_1/cis_1.1.2.2.x.yml | 6 +- tasks/section_1/cis_1.1.2.3.x.yml | 4 +- tasks/section_1/cis_1.1.2.4.x.yml | 4 +- tasks/section_1/cis_1.1.2.5.x.yml | 4 +- tasks/section_1/cis_1.1.2.6.x.yml | 4 +- tasks/section_1/cis_1.1.2.7.x.yml | 4 +- tasks/section_1/cis_1.2.x.yml | 12 +- tasks/section_1/cis_1.3.x.yml | 4 +- tasks/section_1/cis_1.4.x.yml | 39 ++- tasks/section_1/cis_1.5.1.x.yml | 14 +- tasks/section_1/cis_1.6.x.yml | 8 +- tasks/section_1/cis_1.8.x.yml | 4 +- tasks/section_2/cis_2.2.x.yml | 6 +- tasks/section_3/cis_3.1.x.yml | 10 +- tasks/section_3/cis_3.4.2.x.yml | 90 +++--- tasks/section_4/cis_4.1.1.x.yml | 6 +- tasks/section_4/cis_4.1.2.x.yml | 6 +- tasks/section_4/cis_4.2.x.yml | 18 +- tasks/section_4/cis_4.3.x.yml | 20 +- tasks/section_4/cis_4.4.2.x.yml | 30 +- tasks/section_4/cis_4.4.3.1.x.yml | 6 +- tasks/section_4/cis_4.4.3.3.x.yml | 6 +- tasks/section_4/cis_4.4.3.4.x.yml | 56 ++-- tasks/section_4/cis_4.5.1.x.yml | 66 ++--- tasks/section_4/cis_4.5.2.x.yml | 4 +- tasks/section_5/cis_5.1.1.x.yml | 10 +- tasks/section_5/cis_5.1.2.x.yml | 6 +- tasks/section_5/cis_5.1.3.yml | 4 +- tasks/section_5/cis_5.1.4.yml | 10 +- tasks/section_5/cis_5.2.1.x.yml | 16 +- tasks/section_5/cis_5.2.3.x.yml | 2 +- tasks/section_5/cis_5.2.4.x.yml | 38 +-- tasks/section_6/cis_6.1.x.yml | 60 ++-- tasks/section_6/cis_6.2.x.yml | 108 +++---- templates/audit/99_auditd.rules.j2 | 2 +- vars/is_container.yml | 434 ++++++++++++++++------------- 47 files changed, 687 insertions(+), 615 deletions(-) diff --git a/Changelog.md b/Changelog.md index 2df2a612..b1e5a0c9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,10 +6,19 @@ ### Changes and improvements (March24) +Changes to variable naming for those variables discovered +some lint updates + thanks to @bbaassssiiee - #353 - #354 +- #359 +- #360 +- #361 +- #363 +- #364 +- #365 Audit and audit_only changed to run prior to any significant changes diff --git a/README.md b/README.md index 399bed81..75f086db 100644 --- a/README.md +++ b/README.md @@ -47,13 +47,19 @@ Join us on our [Discord Server](https://www.lockdownenterprise.com/discord) to a This role **will make changes to the system** which may have unintended consequences. This is not an auditing tool but rather a remediation tool to be used after an audit has been conducted. -Check Mode is not supported! The role will complete in check mode without errors, but it is not supported and should be used with caution. The RHEL8-CIS-Audit role or a compliance scanner should be used for compliance checking over check mode. +- Testing is the most important thing you can do. -This role was developed against a clean install of the Operating System. If you are implementing to an existing system please review this role for any site specific changes that are needed. +- Check Mode is not supported! The role will complete in check mode without errors, but it is not supported and should be used with caution. The RHEL8-CIS-Audit role or a compliance scanner should be used for compliance checking over check mode. -To use release version please point to main branch and relevant release for the cis benchmark you wish to work with. +- This role was developed against a clean install of the Operating System. If you are implementing to an existing system please review this role for any site specific changes that are needed. -If moving across major releases e.g. v2.0.0 - v3.0.0 there are significant changes to the benchmarks and controls it is suggested to start as a new standard not to upgrade. +- To use release version please point to main branch and relevant release/tag for the cis benchmark you wish to work with. + +- If moving across major releases e.g. v2.0.0 - v3.0.0 there are significant changes to the benchmarks and controls it is suggested to start as a new standard not to upgrade. + +- Containers references vars/is_container.yml this is an example and to be updated for your requirements + +- Did we mention testing?? --- diff --git a/defaults/main.yml b/defaults/main.yml index da0cb0e1..0c419114 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -705,10 +705,10 @@ rhel8cis_pass: warn_age: 7 ## Set the following to true if you wish to adjust accounts greater than rhel8cis_pass['max_days'] -rhel8cis_4_5_1_2_set_max_expiry: false +rhel8cis_set_max_expiry: false ## Add users to be skipped if required -rhel8cis_4_5_1_2_user_skip_list: +rhel8cis_user_skip_list: root rhel8cis_root_umask: '0027' # 0027 or more restrictive diff --git a/handlers/main.yml b/handlers/main.yml index 314de2bd..49d3d7ed 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -15,6 +15,9 @@ masked: false state: reloaded +- name: Reload_sysctl + ansible.builtin.shell: sysctl --system + - name: Sysctl_flush_ipv4_routes ansible.posix.sysctl: name: net.ipv4.route.flush @@ -71,7 +74,7 @@ state: restarted - name: Rebuild_grub - ansible.builtin.shell: "grub2-mkconfig -o {{ grub_cfg.stat.lnk_source }}" + ansible.builtin.shell: "grub2-mkconfig -o {{ discovered_grub_cfg.stat.lnk_source }}" ignore_errors: true # noqa ignore-errors notify: Change_requires_reboot tags: @@ -91,14 +94,14 @@ - name: Auditd_immutable_check ansible.builtin.shell: grep -c "^-e 2" /etc/audit/rules.d/99_auditd.rules changed_when: false - register: auditd_immutable_check + register: discovered_auditd_immutable_check - name: Audit_immutable_fact ansible.builtin.debug: msg: "Reboot required for auditd to apply new rules as immutable set" notify: Change_requires_reboot when: - - auditd_immutable_check.stdout == '1' + - discovered_auditd_immutable_check.stdout == '1' - name: Restart_auditd ansible.builtin.shell: /sbin/service auditd restart diff --git a/tasks/auditd.yml b/tasks/auditd.yml index d8347680..00ed3ecc 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -1,13 +1,12 @@ --- -- name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added +- name: POST | AUDITD | Apply auditd template will for section 5.2.3 - only required rules will be added ansible.builtin.template: src: audit/99_auditd.rules.j2 dest: /etc/audit/rules.d/99_auditd.rules owner: root group: root - mode: 0600 - register: audit_rules_updated + mode: '0600' notify: - Auditd_immutable_check - Audit_immutable_fact diff --git a/tasks/main.yml b/tasks/main.yml index e6a37976..c47d8485 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -56,11 +56,11 @@ ansible.builtin.shell: passwd -S root | grep -E "(Password set, SHA512 crypt|Password locked|root\s(LK|L)\s)" changed_when: false failed_when: false - register: root_passwd_set + register: discovered_root_passwd_set - name: Ensure root password is set ansible.builtin.assert: - that: root_passwd_set.rc == 0 + that: discovered_root_passwd_set.rc == 0 fail_msg: "You have rule 4.5.2.4 enabled this requires that you have a root password set" success_msg: "You have a root password set" @@ -98,11 +98,11 @@ changed_when: false failed_when: false check_mode: false - register: ansible_user_password_set + register: discovered_ansible_user_password_set - name: "Assert that password set for {{ ansible_env.SUDO_USER }} and account not locked" ansible.builtin.assert: - that: ansible_user_password_set.stdout | length != 0 and ansible_user_password_set.stdout != "!!" + that: discovered_ansible_user_password_set.stdout | length != 0 and discovered_ansible_user_password_set.stdout != "!!" fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} has no password set - It can break access" success_msg: "You have a password set for the {{ ansible_env.SUDO_USER }} user" vars: diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 1a653353..7878ae20 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -6,12 +6,12 @@ ansible.builtin.shell: cat /etc/passwd changed_when: false check_mode: false - register: rhel8cis_passwd_file_audit + register: discovered_passwd_file_audit - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries" ansible.builtin.set_fact: - rhel8cis_passwd: "{{ rhel8cis_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" - with_items: "{{ rhel8cis_passwd_file_audit.stdout_lines }}" + rhel8cis_passwd: "{{ discovered_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" + with_items: "{{ discovered_passwd_file_audit.stdout_lines }}" vars: ld_passwd_regex: >- ^(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*) diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 64eb6f5f..78c84e63 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -1,7 +1,7 @@ --- - name: Post Audit | Run post_remediation {{ benchmark }} audit - ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g {{ group_names }}" + ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" @@ -23,12 +23,12 @@ block: - name: Post Audit | Capture data {{ post_audit_outfile }} ansible.builtin.shell: cat {{ post_audit_outfile }} - register: post_audit + register: discovered_post_audit changed_when: false - name: Post Audit | Capture post-audit result ansible.builtin.set_fact: - post_audit_summary: "{{ post_audit.stdout | from_json | json_query(summary) }}" + post_audit_summary: "{{ discovered_post_audit.stdout | from_json | json_query(summary) }}" vars: summary: summary."summary-line" @@ -38,9 +38,9 @@ block: - name: Post Audit | Capture data {{ post_audit_outfile }} ansible.builtin.shell: tail -2 {{ post_audit_outfile }} - register: post_audit + register: discovered_post_audit changed_when: false - name: Post Audit | Capture post-audit result ansible.builtin.set_fact: - post_audit_summary: "{{ post_audit.stdout_lines }}" + post_audit_summary: "{{ discovered_post_audit.stdout_lines }}" diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 4ab3e4ac..75e4d154 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -58,11 +58,11 @@ - name: Pre Audit Setup | Check for goss file ansible.builtin.stat: path: "{{ audit_bin }}" - register: goss_available + register: discovered_goss_available - name: Pre Audit Setup | If audit ensure goss is available ansible.builtin.assert: - that: goss_available.stat.exists + that: discovered_goss_available.stat.exists msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}" - name: Pre Audit Setup | Copy ansible default vars values to test audit @@ -77,7 +77,7 @@ mode: '0600' - name: Pre Audit | Run pre_remediation {{ benchmark }} audit - ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g {{ group_names }}" + ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" @@ -88,14 +88,14 @@ when: - audit_format == "json" block: - - name: capture data {{ pre_audit_outfile }} + - name: Pre Audit | Capture data {{ pre_audit_outfile }} ansible.builtin.shell: cat {{ pre_audit_outfile }} - register: pre_audit + register: discovered_pre_audit changed_when: false - name: Pre Audit | Capture pre-audit result ansible.builtin.set_fact: - pre_audit_summary: "{{ pre_audit.stdout | from_json | json_query(summary) }}" + pre_audit_summary: "{{ discovered_pre_audit.stdout | from_json | json_query(summary) }}" vars: summary: summary."summary-line" @@ -103,14 +103,14 @@ when: - audit_format == "documentation" block: - - name: Pre Audit | capture data {{ pre_audit_outfile }} | documentation format + - name: Pre Audit | Capture data {{ pre_audit_outfile }} | documentation format ansible.builtin.shell: tail -2 {{ pre_audit_outfile }} - register: pre_audit + register: discovered_pre_audit changed_when: false - name: Pre Audit | Capture pre-audit result | documentation format ansible.builtin.set_fact: - pre_audit_summary: "{{ pre_audit.stdout_lines }}" + pre_audit_summary: "{{ discovered_pre_audit.stdout_lines }}" - name: Audit_Only | Run Audit Only when: diff --git a/tasks/prelim.yml b/tasks/prelim.yml index eb8a2b9d..1eade936 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -11,13 +11,13 @@ state: present # List users in order to look files inside each home directory -- name: "PRELIM | AUDIT | List users accounts" - tags: - - always - ansible.builtin.shell: "awk -F: '{print $1}' /etc/passwd" - changed_when: false - check_mode: false - register: users +# - name: "PRELIM | AUDIT | List users accounts" +# tags: +# - always +# ansible.builtin.shell: "awk -F: '{print $1}' /etc/passwd" +# changed_when: false +# check_mode: false +# register: discovered_users - name: "PRELIM | AUDIT | Gather interactive user ID min and max" when: @@ -29,18 +29,18 @@ ansible.builtin.shell: grep ^UID_MIN /etc/login.defs | awk '{print $2}' changed_when: false failed_when: false - register: rhel8cis_min_uid + register: discovered_min_uid - name: "PRELIM | AUDIT | Gather interactive user ID max" ansible.builtin.shell: grep ^UID_MAX /etc/login.defs | awk '{print $2}' changed_when: false failed_when: false - register: rhel8cis_max_uid + register: discovered_max_uid - name: "PRELIM | AUDIT | Setting the fact" ansible.builtin.set_fact: - rhel8uid_interactive_uid_start: "{{ rhel8cis_min_uid.stdout | string }}" - rhel8uid_interactive_uid_stop: "{{ rhel8cis_max_uid.stdout | string }}" + rhel8uid_interactive_uid_start: "{{ discovered_min_uid.stdout | string }}" + rhel8uid_interactive_uid_stop: "{{ discovered_max_uid.stdout | string }}" - name: "PRELIM | AUDIT | Set facts based on boot type" tags: @@ -49,17 +49,17 @@ - name: "PRELIM | AUDIT | Check whether machine is UEFI-based" ansible.builtin.stat: path: /sys/firmware/efi - register: rhel_08_efi_boot + register: discovered_efi_boot - name: "PRELIM | AUDIT | set legacy boot and grub path fact | Bios" - when: not rhel_08_efi_boot.stat.exists + when: not discovered_efi_boot.stat.exists ansible.builtin.set_fact: rhel8cis_legacy_boot: true grub2_path: /etc/grub2.cfg rhel8cis_boot_path: /boot/grub2/ - name: "PRELIM | AUDIT | set grub fact | UEFI" - when: rhel_08_efi_boot.stat.exists + when: discovered_efi_boot.stat.exists ansible.builtin.set_fact: grub2_path: /etc/grub2-efi.cfg rhel8cis_boot_path: "/boot/efi/EFI/{{ansible_facts.distribution | lower }}/" @@ -70,7 +70,7 @@ ansible.builtin.stat: path: "{{ grub2_path }}" changed_when: false - register: grub_cfg + register: discovered_grub_cfg - name: "PRELIM | AUDIT | Gather the package facts before prelim" tags: @@ -114,8 +114,8 @@ - always ansible.builtin.shell: findmnt -kn /dev/shm changed_when: false - failed_when: rhel8cis_dev_shm_present.rc not in [ 0, 1 ] - register: rhel8cis_dev_shm_present + failed_when: discovered_dev_shm_present.rc not in [ 0, 1 ] + register: discovered_dev_shm_present - name: "PRELIM | AUDIT | systemd coredump file check" when: @@ -124,7 +124,7 @@ - always ansible.builtin.stat: path: /etc/systemd/coredump.conf - register: systemd_coredump + register: discovered_systemd_coredump - name: "PRELIM | AUDIT | Ensure crypto-policies-scripts package is installed" tags: @@ -141,16 +141,16 @@ ansible.builtin.shell: 'update-crypto-policies --show' changed_when: false check_mode: false - register: rhel8cis_system_wide_crypto_policy + register: discovered_system_wide_crypto_policy - name: "PRELIM | AUDIT | Gather system-wide crypto-policy | set fact for crypto policy" ansible.builtin.set_fact: - current_crypto_policy: "{{ rhel8cis_system_wide_crypto_policy.stdout.split(':')[0] }}" + current_crypto_policy: "{{ discovered_system_wide_crypto_policy.stdout.split(':')[0] }}" - name: "PRELIM | AUDIT | Gather system-wide crypto-policy module | set fact for crypto submodule" - when: "':' in rhel8cis_system_wide_crypto_policy.stdout" + when: "':' in discovered_system_wide_crypto_policy.stdout" ansible.builtin.set_fact: - current_crypto_module: "{{ rhel8cis_system_wide_crypto_policy.stdout.split(':')[1] }}" + current_crypto_module: "{{ discovered_system_wide_crypto_policy.stdout.split(':')[1] }}" - name: "PRELIM | PATCH | Install dconf if gui" when: @@ -180,7 +180,7 @@ changed_when: false failed_when: false check_mode: false - register: rhel8cis_sudoers_files + register: discovered_sudoers_filess - name: "PRELIM | AUDIT | Check authselect package versions" tags: @@ -257,22 +257,22 @@ when: not rhel8cis_authselect_custom_profile_create ansible.builtin.shell: authselect current changed_when: false - failed_when: authselect_running_config.rc not in [ 0, 1 ] - register: authselect_running_config + failed_when: discovered_authselect_running_config.rc not in [ 0, 1 ] + register: discovered_authselect_running_config - name: "PRELIM | AUDIT | Check authselect profile is selected" ansible.builtin.assert: - that: not rhel8cis_authselect_custom_profile_create and "'example' not in rhel8cis_authselect['custom_profile_name']" or authselect_running_config is defined + that: not rhel8cis_authselect_custom_profile_create and "'example' not in rhel8cis_authselect['custom_profile_name']" or discovered_authselect_running_config is defined success_msg: "Authselect is running and profile is selected" fail_msg: Authselect updates have been selected there are issues with profile selection" - name: "PRELIM | AUDIT | Check profile exists if not created" ansible.builtin.stat: path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}" - register: rhel8cis_4_4_2_1_profile + register: discovered_authselect_profile - name: "PRELIM | AUDIT | Check authselect profile exists if not created" - when: rhel8cis_4_4_2_1_profile.stat.exists + when: discovered_authselect_profile.stat.exists ansible.builtin.assert: that: not rhel8cis_authselect_custom_profile_create success_msg: "Authselect is running and profile is selected" @@ -284,7 +284,7 @@ ansible.builtin.shell: > grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $6 }' changed_when: false - register: interactive_users_home + register: discovered_interactive_users_home - name: "PRELIM | PATCH | Section 5.1 | Configure System Accounting (auditd)" when: rhel8cis_level_2 @@ -297,8 +297,8 @@ - name: "PRELIM | AUDIT | 5.2.4.x | Ensure audit log files are mode 0640 or less permissive | discover file" ansible.builtin.shell: "grep ^log_file /etc/audit/auditd.conf | awk '{ print $NF }'" changed_when: false - failed_when: audit_discovered_logfile.rc not in [0, 1] - register: audit_discovered_logfile + failed_when: discovered_audit_logfile.rc not in [0, 1] + register: discovered_audit_logfile when: - rhel8cis_rule_5_2_4_1 - rhel8cis_rule_5_2_4_2 @@ -332,17 +332,17 @@ file_type: file recurse: true patterns: '*.conf,*.rules' - register: auditd_conf_files - -- name: "PRELIM | AUDIT | Gather accounts with empty password fields" - when: - - rhel8cis_rule_6_2_1 - tags: - - always - ansible.builtin.shell: "cat /etc/shadow | awk -F: '($2 == \"\" ) {j++;print $1; } END {exit j}'" - changed_when: false - check_mode: false - register: empty_password_accounts + register: discovered_auditd_conf_files + +# - name: "PRELIM | AUDIT | Gather accounts with empty password fields" +# when: +# - rhel8cis_rule_6_2_1 +# tags: +# - always +# ansible.builtin.shell: "cat /etc/shadow | awk -F: '($2 == \"\" ) {j++;print $1; } END {exit j}'" +# changed_when: false +# check_mode: false +# register: discovered_empty_password_accounts - name: "PRELIM | AUDIT | Gather UID 0 accounts other than root" when: @@ -352,7 +352,7 @@ ansible.builtin.shell: "cat /etc/passwd | awk -F: '($3 == 0 && $1 != \"root\") {i++;print $1 } END {exit i}'" changed_when: false check_mode: false - register: rhel8cis_uid_zero_accounts_except_root + register: discovered_uid_zero_accounts_except_root ##### Optional ##### @@ -379,11 +379,11 @@ - name: "PRELIM | Optional | If IPv6 disable to stop chronyd listening | Check existence" ansible.builtin.shell: grep -E "OPTIONS=.*-4" /etc/sysconfig/chronyd changed_when: false - failed_when: chrony_ipv6_exists.rc not in [ 0, 1] - register: chrony_ipv6_exists + failed_when: discovered_chrony_ipv6_exists.rc not in [ 0, 1] + register: discovered_chrony_ipv6_exists - name: "PRELIM | Optional | If IPv6 disable to stop chronyd listening" - when: chrony_ipv6_exists.stdout | length == 0 + when: discovered_chrony_ipv6_exists.stdout | length == 0 ansible.builtin.lineinfile: backrefs: true path: /etc/sysconfig/chronyd diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index afb4fd76..5072c81b 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -18,7 +18,7 @@ regexp: "^(#)?install cramfs(\\s|$)" line: "install cramfs /bin/true" create: true - mode: 0600 + mode: '0600' - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | blacklist" ansible.builtin.lineinfile: @@ -98,11 +98,11 @@ create: true mode: '0600' - - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | Disable squashfs" + - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | Disable hfs" when: - not system_is_container community.general.modprobe: - name: squashfs + name: hfs state: absent - name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available" diff --git a/tasks/section_1/cis_1.1.2.2.x.yml b/tasks/section_1/cis_1.1.2.2.x.yml index 48efae6d..42c04a0d 100644 --- a/tasks/section_1/cis_1.1.2.2.x.yml +++ b/tasks/section_1/cis_1.1.2.2.x.yml @@ -18,12 +18,12 @@ block: - name: "1.1.2.2.1 | PATCH | Ensure /dev/shm is a separate partition | Absent" - when: rhel8cis_dev_shm_present is undefined + when: discovered_dev_shm_present is undefined ansible.builtin.debug: msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" - name: "1.1.2.2.1 | PATCH | Ensure /dev/shm is a separate partition | Present" - when: rhel8cis_dev_shm_present is undefined + when: discovered_dev_shm_present is undefined ansible.builtin.import_tasks: file: warning_facts.yml @@ -32,7 +32,7 @@ 1.1.2.2.3 | PATCH | Ensure nosuid option set on /dev/shm partition 1.1.2.2.4 | PATCH | Ensure noexec option set on /dev/shm partition" when: - - rhel8cis_dev_shm_present is defined + - discovered_dev_shm_present is defined - rhel8cis_rule_1_1_2_2_2 or rhel8cis_rule_1_1_2_2_3 or rhel8cis_rule_1_1_2_2_4 diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml index 2d28f9a8..ee6d924a 100644 --- a/tasks/section_1/cis_1.1.2.3.x.yml +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -20,8 +20,8 @@ - name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home | Warn if partition is absent" ansible.builtin.debug: msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: home_mount_absent - changed_when: home_mount_absent.skipped is undefined + register: discovered_home_mount_absent + changed_when: discovered_home_mount_absent.skipped is undefined - name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home | Present" ansible.builtin.import_tasks: warning_facts.yml diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml index 384a64df..0dff27d6 100644 --- a/tasks/section_1/cis_1.1.2.4.x.yml +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -5,8 +5,8 @@ - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Warn if partition is absent" ansible.builtin.debug: msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: var_mount_absent - changed_when: var_mount_absent.skipped is undefined + register: discovered_var_mount_absent + changed_when: discovered_var_mount_absent.skipped is undefined - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Present" ansible.builtin.import_tasks: diff --git a/tasks/section_1/cis_1.1.2.5.x.yml b/tasks/section_1/cis_1.1.2.5.x.yml index c0332eaa..49b913f3 100644 --- a/tasks/section_1/cis_1.1.2.5.x.yml +++ b/tasks/section_1/cis_1.1.2.5.x.yml @@ -20,8 +20,8 @@ - name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp | Warn if partition is absent" ansible.builtin.debug: msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: var_tmp_mount_absent - changed_when: var_tmp_mount_absent.skipped is undefined + register: discovered_var_tmp_mount_absent + changed_when: discovered_var_tmp_mount_absent.skipped is undefined - name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp | Present" ansible.builtin.import_tasks: diff --git a/tasks/section_1/cis_1.1.2.6.x.yml b/tasks/section_1/cis_1.1.2.6.x.yml index ce9f79e7..390fc415 100644 --- a/tasks/section_1/cis_1.1.2.6.x.yml +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -19,8 +19,8 @@ - name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log | Warn if partition is absent" ansible.builtin.debug: msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: var_log_mount_absent - changed_when: var_log_mount_absent.skipped is undefined + register: discovered_var_log_mount_absent + changed_when: discovered_var_log_mount_absent.skipped is undefined - name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log | Present" ansible.builtin.import_tasks: diff --git a/tasks/section_1/cis_1.1.2.7.x.yml b/tasks/section_1/cis_1.1.2.7.x.yml index 7463e082..6ebbfdb7 100644 --- a/tasks/section_1/cis_1.1.2.7.x.yml +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -19,8 +19,8 @@ - name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Warn if partition is absent" ansible.builtin.debug: msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: var_log_audit_mount_absent - changed_when: var_log_audit_mount_absent.skipped is undefined + register: discovered_var_log_audit_mount_absent + changed_when: discovered_var_log_audit_mount_absent.skipped is undefined - name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Present" ansible.builtin.import_tasks: diff --git a/tasks/section_1/cis_1.2.x.yml b/tasks/section_1/cis_1.2.x.yml index 6c2cf944..4cfa9470 100644 --- a/tasks/section_1/cis_1.2.x.yml +++ b/tasks/section_1/cis_1.2.x.yml @@ -33,7 +33,7 @@ ansible.builtin.find: paths: /etc/yum.repos.d patterns: "*.repo" - register: yum_repos + register: discovered_yum_repos changed_when: false - name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos" @@ -41,7 +41,7 @@ name: "{{ item.path }}" regexp: "^gpgcheck=0" replace: "gpgcheck=1" - loop: "{{ yum_repos.files }}" + loop: "{{ discovered_yum_repos.files }}" loop_control: label: "{{ item.path }}" @@ -66,7 +66,7 @@ ansible.builtin.find: paths: /etc/yum.repos.d patterns: "*.repo" - register: yum_repos + register: discovered_yum_repos changed_when: false - name: "1.2.3 | PATCH | Ensure repo_gpgcheck is globally activated | Update yum.repos" @@ -74,7 +74,7 @@ name: "{{ item.path }}" regexp: "^repo_gpgcheck=0" replace: "repo_gpgcheck=1" - loop: "{{ yum_repos.files }}" + loop: "{{ discovered_yum_repos.files }}" loop_control: label: "{{ item.path }}" @@ -101,14 +101,14 @@ ansible.builtin.shell: dnf repolist changed_when: false failed_when: false - register: dnf_configured + register: discovered_dnf_configured check_mode: false - name: "1.2.4 | AUDIT | Ensure package manager repositories are configured | Display repo list" ansible.builtin.debug: msg: - "Warning!! Below are the configured repos. Please review and make sure all align with site policy" - - "{{ dnf_configured.stdout_lines }}" + - "{{ discovered_dnf_configured.stdout_lines }}" - name: "1.2.4 | AUDIT | Ensure package manager repositories are configured | Warn Count" ansible.builtin.import_tasks: diff --git a/tasks/section_1/cis_1.3.x.yml b/tasks/section_1/cis_1.3.x.yml index 95f383e9..9c82fe44 100644 --- a/tasks/section_1/cis_1.3.x.yml +++ b/tasks/section_1/cis_1.3.x.yml @@ -24,8 +24,8 @@ - name: "1.3.2 | PATCH | Ensure permissions on bootloader config are configured" when: - rhel8cis_rule_1_3_2 - - grub_cfg.stat.exists - - grub_cfg.stat.islnk + - discovered_grub_cfg.stat.exists + - discovered_grub_cfg.stat.islnk tags: - level1-server - level1-workstation diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index 631aac39..818b5eba 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -11,13 +11,12 @@ - sysctl - NIST800-53R5_CM-6 - rule_1.4.1 - ansible.posix.sysctl: - name: kernel.randomize_va_space - value: '2' - reload: true - sysctl_file: /etc/sysctl.d/60-kernel_sysctl.conf - sysctl_set: true - ignoreerrors: true + notify: Reload_sysctl + ansible.builtin.lineinfile: + path: /etc/sysctl.d/60-kernel_sysctl.conf + regexp: kernel.randomize_va_space + line: kernel.randomize_va_space = 2 + create: true - name: "1.4.2 | PATCH | Ensure ptrace_scope is restricted" when: @@ -30,13 +29,22 @@ - sysctl - NIST800-53R5_CM-6 - rule_1.4.2 - ansible.posix.sysctl: - name: kernel.yama.ptrace_scope - value: '1' - reload: true - sysctl_file: /etc/sysctl.d/60-kernel_sysctl.conf - sysctl_set: true - ignoreerrors: true + notify: Reload_sysctl + block: + - name: Ensure ptrace_scope is restricted | Set file + ansible.builtin.lineinfile: + path: /etc/sysctl.d/60-kernel_sysctl.conf + regexp: kernel.yama.ptrace_scope + line: kernel.yama.ptrace_scope = 1 + create: true + + - name: Ensure ptrace_scope is restricted | comment out other entry + ansible.builtin.lineinfile: + path: /lib/sysctl.d/10-default-yama-scope.conf + backrefs: true + regexp: ^(\s*kernel.yama.ptrace_scope.*) + line: '# \1' + create: true - name: "1.4.3 | PATCH | Ensure core dump backtraces are disabled" tags: @@ -51,13 +59,14 @@ path: /etc/systemd/coredump.conf regexp: 'ProcessSizeMax=' line: 'ProcessSizeMax=0' + create: true when: - rhel8cis_rule_1_4_3 - name: "1.4.4 | PATCH | Ensure core dump storage is disabled" when: - rhel8cis_rule_1_4_4 - - systemd_coredump.stat.exists + - discovered_systemd_coredump.stat.exists tags: - level1-server - level1-workstation diff --git a/tasks/section_1/cis_1.5.1.x.yml b/tasks/section_1/cis_1.5.1.x.yml index 7b229530..8a24f695 100644 --- a/tasks/section_1/cis_1.5.1.x.yml +++ b/tasks/section_1/cis_1.5.1.x.yml @@ -30,8 +30,6 @@ path: /etc/default/grub regexp: '(selinux|enforcing)\s*=\s*0\s*' replace: '' - register: selinux_grub_patch - ignore_errors: true # noqa ignore-errors # State set to enforcing because control 1.5.1.5 requires enforcing to be set - name: "1.5.1.3 | PATCH | Ensure SELinux policy is configured" @@ -104,21 +102,21 @@ block: - name: "1.5.1.6 | AUDIT | Ensure no unconfined services exist | Find the unconfined services" ansible.builtin.shell: ps -eZ | grep unconfined_service_t | egrep -vw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }' - register: rhel8cis_1_5_1_6_unconf_services + register: discovered_unconf_services failed_when: false changed_when: false - name: "1.5.1.6 | WARN | Ensure no unconfined services exist | Message on unconfined services" when: - - rhel8cis_1_5_1_6_unconf_services is defined - - rhel8cis_1_5_1_6_unconf_services.stdout | length > 0 + - discovered_unconf_services is defined + - discovered_unconf_services.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! You have unconfined services: {{ rhel8cis_1_5_1_6_unconf_services.stdout_lines }}" + msg: "Warning!! You have unconfined services: {{ discovered_unconf_services.stdout_lines }}" - name: "1.5.1.6 | WARN | Ensure no unconfined services exist | warning count" when: - - rhel8cis_1_5_1_6_unconf_services is defined - - rhel8cis_1_5_1_6_unconf_services.stdout | length > 0 + - discovered_unconf_services is defined + - discovered_unconf_services.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml index 5f672ee0..41712b29 100644 --- a/tasks/section_1/cis_1.6.x.yml +++ b/tasks/section_1/cis_1.6.x.yml @@ -18,7 +18,7 @@ - name: "1.6.1 | PATCH | Ensure system-wide crypto policy is not legacy" when: - - rhel8cis_system_wide_crypto_policy.stdout not in rhel8cis_crypto_policy + - discovered_system_wide_crypto_policy.stdout not in rhel8cis_crypto_policy ansible.builtin.shell: | update-crypto-policies --set "{{ rhel8cis_full_crypto_policy }}" update-crypto-policies @@ -26,7 +26,7 @@ - name: "1.6.2 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support" when: - rhel8cis_rule_1_6_2 - - "'NO-SHA1' not in rhel8cis_system_wide_crypto_policy.stdout" + - "'NO-SHA1' not in discovered_system_wide_crypto_policy.stdout" tags: - level1-server - level1-workstation @@ -47,7 +47,7 @@ - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables cbc for ssh" when: - rhel8cis_rule_1_6_3 - - "'NO-SSHCBC' not in rhel8cis_system_wide_crypto_policy.stdout" + - "'NO-SSHCBC' not in discovered_system_wide_crypto_policy.stdout" tags: - level1-server - level1-workstation @@ -68,7 +68,7 @@ - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits" when: - rhel8cis_rule_1_6_4 - - "'NO-WEAKMAC' not in rhel8cis_system_wide_crypto_policy.stdout" + - "'NO-WEAKMAC' not in discovered_system_wide_crypto_policy.stdout" tags: - level1-server - level1-workstation diff --git a/tasks/section_1/cis_1.8.x.yml b/tasks/section_1/cis_1.8.x.yml index b665c17e..dcc2f2aa 100644 --- a/tasks/section_1/cis_1.8.x.yml +++ b/tasks/section_1/cis_1.8.x.yml @@ -35,7 +35,7 @@ create: true owner: root group: root - mode: 0644 + mode: '0644' notify: Reload_dconf loop: - { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' } @@ -80,7 +80,7 @@ create: true owner: root group: root - mode: 0644 + mode: '0644' notify: Reload_dconf loop: - { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' } diff --git a/tasks/section_2/cis_2.2.x.yml b/tasks/section_2/cis_2.2.x.yml index adfc8a91..7d559a1f 100644 --- a/tasks/section_2/cis_2.2.x.yml +++ b/tasks/section_2/cis_2.2.x.yml @@ -720,16 +720,16 @@ - name: "2.2.22 | AUDIT | Ensure only approved services are listening on a network interface | Get list of services" ansible.builtin.shell: systemctl list-units --type=service changed_when: false - failed_when: rhel8cis_2_2_22_services.rc not in [ 0, 1 ] + failed_when: discovered_running_services.rc not in [ 0, 1 ] check_mode: false - register: rhel8cis_2_2_22_services + register: discovered_running_services - name: "2.2.22 | AUDIT | Ensure only approved services are listening on a network interface | Display list of services" ansible.builtin.debug: msg: - "Warning!! Below are the list of services, both active and inactive" - "Please review to make sure all are essential" - - "{{ rhel8cis_2_2_22_services.stdout_lines }}" + - "{{ discovered_running_services.stdout_lines }}" - name: "2.2.22 | AUDIT | Ensure only approved services are listening on a network interface | Warn Count" ansible.builtin.import_tasks: diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index c2f83bd4..1b5d830b 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -62,17 +62,17 @@ changed_when: false failed_when: false check_mode: false - register: rhel_08_nmcli_available + register: discovered_nmcli_available - name: "3.1.2 | AUDIT | Ensure wireless interfaces are disabled | Check if wifi is enabled" - when: rhel_08_nmcli_available.rc == 0 + when: discovered_nmcli_available.rc == 0 ansible.builtin.shell: nmcli radio wifi - register: rhel_08_wifi_enabled - changed_when: rhel_08_wifi_enabled.stdout != "disabled" + register: discovered_wifi_enabled + changed_when: discovered_wifi_enabled.stdout != "disabled" failed_when: false - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Disable wifi if enabled" - when: rhel_08_wifi_enabled is changed # noqa: no-handler + when: discovered_wifi_enabled is changed # noqa: no-handler ansible.builtin.shell: nmcli radio all off changed_when: false failed_when: false diff --git a/tasks/section_3/cis_3.4.2.x.yml b/tasks/section_3/cis_3.4.2.x.yml index 2be48415..5b0a3462 100644 --- a/tasks/section_3/cis_3.4.2.x.yml +++ b/tasks/section_3/cis_3.4.2.x.yml @@ -16,29 +16,29 @@ ansible.builtin.shell: nft list ruleset | grep 'hook input' changed_when: false failed_when: false - register: rhel8cis_3_4_2_1_input_chains + register: discovered_input_chains - name: "3.4.2.1 | AUDIT | Ensure nftables base chains exist | Get current chains for FORWARD" ansible.builtin.shell: nft list ruleset | grep 'hook forward' changed_when: false failed_when: false - register: rhel8cis_3_4_2_1_forward_chains + register: discovered_forward_chains - name: "3.4.2.1 | AUDIT | Ensure nftables base chains exist | Get current chains for OUTPUT" ansible.builtin.shell: nft list ruleset | grep 'hook output' changed_when: false failed_when: false - register: rhel8cis_3_4_2_1_output_chains + register: discovered_output_chains - name: "3.4.2.1 | AUDIT | Ensure nftables base chains exist | Display chains for review" ansible.builtin.debug: msg: - "Below are the current INPUT chains" - - "{{ rhel8cis_3_4_2_1_input_chains.stdout_lines }}" + - "{{ discovered_input_chains.stdout_lines }}" - "Below are the current FORWARD chains" - - "{{ rhel8cis_3_4_2_1_forward_chains.stdout_lines }}" + - "{{ discovered_forward_chains.stdout_lines }}" - "Below are teh current OUTPUT chains" - - "{{ rhel8cis_3_4_2_1_output_chains.stdout_lines }}" + - "{{ discovered_output_chains.stdout_lines }}" when: not rhel8cis_nft_tables_autochaincreate - name: "3.4.2.1 | PATCH | Ensure nftables base chains exist | Create chains if needed" @@ -66,36 +66,36 @@ ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'iif "lo" accept' changed_when: false failed_when: false - register: rhel8cis_3_4_2_2_iiflo + register: discovered_iiflo - name: "3.4.2.2 | AUDIT | Ensure host based firewall loopback traffic is configured | Gather ip saddr existence | nftables" ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip saddr' changed_when: false failed_when: false - register: rhel8cis_3_4_2_2_ipsaddr + register: discovered_ipsaddr - name: "3.4.2.2 | AUDIT | Ensure host based firewall loopback traffic is configured | Gather ip6 saddr existence | nftables" ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip6 saddr' changed_when: false failed_when: false - register: rhel8cis_3_4_2_2_ip6saddr + register: discovered_ip6saddr - name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | Set iif lo accept rule | nftables" ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input iif lo accept - when: '"iif \"lo\" accept" not in rhel8cis_3_4_2_2_iiflo.stdout' + when: '"iif \"lo\" accept" not in discovered_iiflo.stdout' - name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | Set ip sddr rule | nftables" ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip saddr 127.0.0.0/8 counter drop - when: '"ip saddr 127.0.0.0/8 counter packets 0 bytes 0 drop" not in rhel8cis_3_4_2_2_ipsaddr.stdout' + when: '"ip saddr 127.0.0.0/8 counter packets 0 bytes 0 drop" not in discovered_ipsaddr.stdout' - name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | Set ip6 saddr rule | nftables" ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip6 saddr ::1 counter drop - when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in rhel8cis_3_4_2_4_ip6saddr.stdout' + when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in discovered_ip6saddr.stdout' - name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | firewalld" when: - rhel8cis_firewall == "firewalld" - - rhel8cis_rule_3_4_2_4 + - rhel8cis_rule_3_4_2_2 tags: - level1-server - level1-workstation @@ -103,15 +103,25 @@ - nftables - NIST800-53R5_CA-9 - rule_3.4.2.2 - ansible.posix.firewalld: - rich_rule: "{{ item }}" - zone: "{{ rhel8cis_default_zone }}" - permanent: true - immediate: true - state: enabled - loop: - - rule family="ipv4" source address="127.0.0.1" destination not address="127.0.0.1" drop - - rule family="ipv6" source address="::1" destination not address="::1" drop + block: + - name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | add interface" + ansible.posix.firewalld: + zone: trusted + interface: lo + permanent: true + immediate: true + state: enabled + + - name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | add loopback rule" + ansible.posix.firewalld: + rich_rule: "{{ item }}" + zone: trusted + permanent: true + immediate: true + state: enabled + loop: + - rule family="ipv4" source address="127.0.0.1" destination not address="127.0.0.1" drop + - rule family="ipv6" source address="::1" destination not address="::1" drop - name: "3.4.2.3 | AUDIT | Ensure firewalld drops unnecessary services and ports" when: @@ -130,13 +140,13 @@ changed_when: false failed_when: false check_mode: false - register: rhel8cis_3_4_2_3_servicesport + register: discovered_servicesport - name: "3.4.2.3 | AUDIT | Ensure firewalld drops unnecessary services and ports | Show services and ports" ansible.builtin.debug: msg: - "The items below are the services and ports that are accepted, please correct as needed" - - "{{ rhel8cis_3_4_2_3_servicesport.stdout_lines }}" + - "{{ discovered_servicesport.stdout_lines }}" - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured" when: @@ -153,37 +163,37 @@ ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state' changed_when: false failed_when: false - register: rhel8cis_3_4_2_4_inconnectionrule + register: discovered_inconnectionrule - name: "3.4.2.4| AUDIT | Ensure nftables established connections are configured | Gather outbound connection rules" ansible.builtin.shell: nft list ruleset | awk '/hook output/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state' changed_when: false failed_when: false - register: rhel8cis_3_4_2_4_outconnectionrule + register: discovered_outconnectionrule - name: "3.4.2.4| PATCH | Ensure nftables established connections are configured | Add input tcp established accept policy" ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept - when: '"ip protocol tcp ct state established accept" not in rhel8cis_3_4_2_4_inconnectionrule.stdout' + when: '"ip protocol tcp ct state established accept" not in discovered_inconnectionrule.stdout' - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add input udp established accept policy" ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol udp ct state established accept - when: '"ip protocol udp ct state established accept" not in rhel8cis_3_4_2_4_inconnectionrule.stdout' + when: '"ip protocol udp ct state established accept" not in discovered_inconnectionrule.stdout' - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add input icmp established accept policy" ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol icmp ct state established accept - when: '"ip protocol icmp ct state established accept" not in rhel8cis_3_4_2_4_inconnectionrule.stdout' + when: '"ip protocol icmp ct state established accept" not in discovered_inconnectionrule.stdout' - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add output tcp new, related, established accept policy" ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol tcp ct state new,related,established accept - when: '"ip protocol tcp ct state established,related,new accept" not in rhel8cis_3_4_2_4_outconnectionrule.stdout' + when: '"ip protocol tcp ct state established,related,new accept" not in discovered_outconnectionrule.stdout' - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add output udp new, related, established accept policy" ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol udp ct state new,related,established accept - when: '"ip protocol udp ct state established,related,new accept" not in rhel8cis_3_4_2_4_outconnectionrule.stdout' + when: '"ip protocol udp ct state established,related,new accept" not in discovered_outconnectionrule.stdout' - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add output icmp new, related, established accept policy" ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol icmp ct state new,related,established accept - when: '"ip protocol icmp ct state established,related,new accept" not in rhel8cis_3_4_2_4_outconnectionrule.stdout' + when: '"ip protocol icmp ct state established,related,new accept" not in discovered_outconnectionrule.stdout' - name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy" when: @@ -201,38 +211,38 @@ ansible.builtin.shell: nft list table inet "{{ rhel8cis_nft_tables_tablename }}" | grep 'hook input' failed_when: false changed_when: false - register: rhel8cis_3_4_2_5_inputpolicy + register: discovered_inputpolicy - name: "3.4.2.5 | AUDIT | Ensure nftables default deny firewall policy | Check for hook forward deny policy" ansible.builtin.shell: nft list table inet "{{ rhel8cis_nft_tables_tablename }}" | grep 'hook forward' failed_when: false changed_when: false - register: rhel8cis_3_4_2_5_forwardpolicy + register: discovered_forwardpolicy - name: "3.4.2.5 | AUDIT | Ensure nftables default deny firewall policy | Check for hook output deny policy" ansible.builtin.shell: nft list table inet "{{ rhel8cis_nft_tables_tablename }}" | grep 'hook output' failed_when: false changed_when: false - register: rhel8cis_3_4_2_5_outputpolicy + register: discovered_outputpolicy - name: "3.4.2.5 | AUDIT | Ensure nftables default deny firewall policy | Check for SSH allow" ansible.builtin.shell: nft list table inet "{{ rhel8cis_nft_tables_tablename }}" | grep 'ssh' failed_when: false changed_when: false - register: rhel8cis_3_4_2_5_sshallowcheck + register: discovered_sshallowcheck - name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy | Enable SSH traffic" ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input tcp dport ssh accept - when: '"tcp dport ssh accept" not in rhel8cis_3_4_2_5_sshallowcheck.stdout' + when: '"tcp dport ssh accept" not in discovered_sshallowcheck.stdout' - name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy | Set hook input deny policy" ansible.builtin.command: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" input { policy drop \; } - when: '"type filter hook input priority 0; policy drop;" not in rhel8cis_3_4_2_5_inputpolicy.stdout' + when: '"type filter hook input priority 0; policy drop;" not in discovered_inputpolicy.stdout' - name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy | Create hook forward deny policy" ansible.builtin.command: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" forward { policy drop \; } - when: '"type filter hook forward priority 0; policy drop;" not in rhel8cis_3_4_2_5_forwardpolicy.stdout' + when: '"type filter hook forward priority 0; policy drop;" not in discovered_forwardpolicy.stdout' - name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy | Create hook output deny policy" ansible.builtin.command: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" output { policy drop \; } - when: '"type filter hook output priority 0; policy drop;" not in rhel8cis_3_4_2_5_outputpolicy.stdout' + when: '"type filter hook output priority 0; policy drop;" not in discovered_outputpolicy.stdout' diff --git a/tasks/section_4/cis_4.1.1.x.yml b/tasks/section_4/cis_4.1.1.x.yml index 59aa8adb..b70ee61f 100644 --- a/tasks/section_4/cis_4.1.1.x.yml +++ b/tasks/section_4/cis_4.1.1.x.yml @@ -130,7 +130,7 @@ state: directory owner: root group: root - mode: 0700 + mode: '0700' - name: "4.1.1.8 | PATCH | Ensure cron is restricted to authorized users" when: @@ -153,12 +153,12 @@ - name: "4.1.1.8 | PATCH | Ensure cron is restricted to authorized users | Check if cron.allow exists" ansible.builtin.stat: path: "/etc/cron.allow" - register: rhel8cis_4_1_1_8_cron_allow_state + register: discovered_cron_allow_state - name: "4.1.1.8 | PATCH | Ensure cron is restricted to authorized users | Ensure cron.allow is restricted to authorized users" ansible.builtin.file: path: /etc/cron.allow - state: '{{ "file" if rhel8cis_4_1_1_8_cron_allow_state.stat.exists else "touch" }}' + state: '{{ "file" if discovered_cron_allow_state.stat.exists else "touch" }}' owner: root group: root mode: g-wx,o-rwx diff --git a/tasks/section_4/cis_4.1.2.x.yml b/tasks/section_4/cis_4.1.2.x.yml index 202c7f6c..b42dd300 100644 --- a/tasks/section_4/cis_4.1.2.x.yml +++ b/tasks/section_4/cis_4.1.2.x.yml @@ -21,12 +21,12 @@ - name: "4.1.2.1 | PATCH | Ensure at is restricted to authorized users | Check if at.allow exists" ansible.builtin.stat: path: "/etc/at.allow" - register: rhel8cis_4_1_2_1_at_allow_state + register: discovered_at_allow_state - name: "4.1.2.1 | PATCH | Ensure at is restricted to authorized users | Ensure at.allow is restricted to authorized users" ansible.builtin.file: path: /etc/at.allow - state: '{{ "file" if rhel8cis_4_1_2_1_at_allow_state.stat.exists else "touch" }}' + state: '{{ "file" if discovered_at_allow_state.stat.exists else "touch" }}' owner: root group: root - mode: 0600 + mode: '0600' diff --git a/tasks/section_4/cis_4.2.x.yml b/tasks/section_4/cis_4.2.x.yml index 8e448d83..37a9cdda 100644 --- a/tasks/section_4/cis_4.2.x.yml +++ b/tasks/section_4/cis_4.2.x.yml @@ -39,15 +39,15 @@ patterns: 'ssh_host_*_key' recurse: true file_type: any - register: rhel8cis_4_2_2_ssh_private_host_key + register: discovered_ssh_private_host_key - name: "4.2.2 | PATCH | Ensure permissions on SSH private host key files are configured | Set permissions on SSH private host keys" ansible.builtin.file: path: "{{ item.path }}" owner: root group: root - mode: 0600 - loop: "{{ rhel8cis_4_2_2_ssh_private_host_key.files }}" + mode: '0600' + loop: "{{ discovered_ssh_private_host_key.files }}" loop_control: label: "{{ item.path }}" @@ -70,15 +70,15 @@ patterns: 'ssh_host_*_key.pub' recurse: true file_type: any - register: rhel8cis_4_2_3_ssh_public_host_key + register: discovered_ssh_public_host_key - name: "4.2.3 | PATCH | Ensure permissions on SSH public host key files are configured | Set permissions on SSH public host keys" ansible.builtin.file: path: "{{ item.path }}" owner: root group: root - mode: 0644 - loop: "{{ rhel8cis_4_2_3_ssh_public_host_key.files }}" + mode: '0644' + loop: "{{ discovered_ssh_public_host_key.files }}" loop_control: label: "{{ item.path }}" @@ -477,12 +477,12 @@ block: - name: "4.2.22 | AUDIT | Ensure system-wide crypto policy is not over-ridden" ansible.builtin.shell: grep -i '^\s*CRYPTO_POLICY=' /etc/sysconfig/sshd - failed_when: ( crypto_policy_override.rc not in [ 0, 1 ] ) + failed_when: ( discovered_crypto_policy_override.rc not in [ 0, 1 ] ) changed_when: false - register: crypto_policy_override + register: discovered_crypto_policy_override - name: "4.2.22 | PATCH | Ensure system-wide crypto policy is not over-ridden" ansible.builtin.shell: sed -ri "s/^\s*(CRYPTO_POLICY\s*=.*)$/# \1/" /etc/sysconfig/sshd notify: Restart_sshd when: - - crypto_policy_override.stdout | length > 0 + - discovered_crypto_policy_override.stdout | length > 0 diff --git a/tasks/section_4/cis_4.3.x.yml b/tasks/section_4/cis_4.3.x.yml index 2978b308..cfc15781 100644 --- a/tasks/section_4/cis_4.3.x.yml +++ b/tasks/section_4/cis_4.3.x.yml @@ -64,7 +64,7 @@ regexp: '^([^#|{% if system_is_ec2 %}ec2-user{% endif %}].*)NOPASSWD(.*)' replace: '\1PASSWD\2' validate: '/usr/sbin/visudo -cf %s' - loop: "{{ rhel8cis_sudoers_files.stdout_lines }}" + loop: "{{ discovered_sudoers_filess.stdout_lines }}" - name: "4.3.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally" when: @@ -82,7 +82,7 @@ regexp: '^([^#].*)!authenticate(.*)' replace: '\1authenticate\2' validate: '/usr/sbin/visudo -cf %s' - loop: "{{ rhel8cis_sudoers_files.stdout_lines }}" + loop: "{{ discovered_sudoers_filess.stdout_lines }}" - name: "4.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly" when: @@ -99,10 +99,10 @@ ansible.builtin.shell: grep -is 'timestamp_timeout' /etc/sudoers /etc/sudoers.d/* | cut -d":" -f1 | uniq | sort changed_when: false failed_when: false - register: rhel8cis_4_3_6_timeout_files + register: discovered_timeout_files - name: "4.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if no results" - when: rhel8cis_4_3_6_timeout_files.stdout | length == 0 + when: discovered_timeout_files.stdout | length == 0 ansible.builtin.lineinfile: path: /etc/sudoers regexp: 'Defaults timestamp_timeout=' @@ -110,13 +110,13 @@ validate: '/usr/sbin/visudo -cf %s' - name: "4.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if has results" - when: rhel8cis_4_3_6_timeout_files.stdout | length > 0 + when: discovered_timeout_files.stdout | length > 0 ansible.builtin.replace: path: "{{ item }}" regexp: 'timestamp_timeout=(\d+)' replace: "timestamp_timeout={{ rhel8cis_sudo_timestamp_timeout }}" validate: '/usr/sbin/visudo -cf %s' - loop: "{{ rhel8cis_4_3_6_timeout_files.stdout_lines }}" + loop: "{{ discovered_timeout_files.stdout_lines }}" - name: "4.3.7 | PATCH | Ensure access to the su command is restricted" when: @@ -135,17 +135,17 @@ ansible.builtin.group: name: "{{ rhel8cis_sugroup }}" state: present - register: rhel8cis_4_3_7_sugroup + register: discovered_sugroup - name: "4.3.7 | PATCH | Ensure access to the su command is restricted | remove users from group" ansible.builtin.lineinfile: path: /etc/group - regexp: '^{{ rhel8cis_sugroup }}(:.:.*:).*$' - line: '{{ rhel8cis_sugroup }}\g<1>' + regexp: '^{{ discovered_sugroup }}(:.:.*:).*$' + line: '{{ discovered_sugroup }}\g<1>' backrefs: true - name: "4.3.7 | PATCH | Ensure access to the su command is restricted | Setting pam_wheel to use_uid" ansible.builtin.lineinfile: path: /etc/pam.d/su regexp: '^(#)?auth\s+required\s+pam_wheel\.so' - line: 'auth required pam_wheel.so use_uid group={{ rhel8cis_sugroup }}' + line: 'auth required pam_wheel.so use_uid group={{ discovered_sugroup }}' diff --git a/tasks/section_4/cis_4.4.2.x.yml b/tasks/section_4/cis_4.4.2.x.yml index e7e64cee..08ef1284 100644 --- a/tasks/section_4/cis_4.4.2.x.yml +++ b/tasks/section_4/cis_4.4.2.x.yml @@ -17,8 +17,8 @@ - name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used | Create custom profiles" when: - rhel8cis_authselect_custom_profile_create - - authselect_running_config.stdout is not defined - - not rhel8cis_4_4_2_1_profile.stat.exists + - discovered_authselect_running_config.stdout is not defined + - not discovered_authselect_profile.stat.exists ansible.builtin.shell: "/usr/bin/authselect create-profile {{ rhel8cis_authselect['custom_profile_name'] }} -b {{ rhel8cis_authselect['default_file_to_copy'] }}" args: creates: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}" @@ -26,7 +26,7 @@ - name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used | Select profiles" when: - rhel8cis_authselect_custom_profile_select - - (authselect_running_config.stdout is defined and "rhel8cis_authselect['custom_profile_name'] not in authselect_running_config.stdout") + - (discovered_authselect_running_config.stdout is defined and "rhel8cis_authselect['custom_profile_name'] not in discovered_authselect_running_config.stdout") ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel8cis_authselect['custom_profile_name'] }}{% if rhel8cis_rule_4_4_2_2 %} with-faillock{% endif %}{% if rhel8cis_rule_4_4_2_4 %} with-pwhistory{% endif %}{% if rhel8cis_rule_4_4_3_4_1 %} without-nullok{% endif %} --force" - name: "4.4.2.2 | PATCH | Ensure pam_faillock module is enabled" @@ -49,11 +49,11 @@ - name: "4.4.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config" ansible.builtin.shell: authselect current | grep faillock changed_when: false - failed_when: rhel8cis_authselect_current.rc not in [ 0, 1 ] - register: rhel8cis_authselect_current + failed_when: discovered_authselect_current.rc not in [ 0, 1 ] + register: discovered_authselect_current - name: "4.4.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" - when: rhel8cis_authselect_current.rc != 0 + when: discovered_authselect_current.rc != 0 ansible.builtin.shell: "authselect enable-feature with-faillock" - name: "4.4.2.3 | PATCH | Ensure pam_pwquality module is enabled" @@ -74,10 +74,10 @@ grep -P -- '\bpam_pwquality\.so\b' /etc/pam.d/{password,system}-auth changed_when: false failed_when: rhel8cis_pwquality_enabled.rc not in [ 0, 1 ] - register: rhel8cis_pwquality_enabled + register: discovered_pwquality_enabled - name: "4.4.2.3 | PATCH | Ensure pam_pwquality module is enabled | system-auth" - when: "'system-auth:password' not in rhel8cis_pwquality_enabled.stdout" + when: "'system-auth:password' not in discovered_pwquality_enabled.stdout" ansible.builtin.lineinfile: backrefs: true insertbefore: "{{ item.before | default (omit) }}" @@ -88,7 +88,7 @@ - { regexp: '^(password\s+)(required|requisite|sufficient)(\s+pam_pwquality.so.*)(.*)', line: '\1requisite\3\4', before: '^password\s+[default=1 ignore=ignore success=ok]' } - name: "4.4.2.3 | PATCH | Ensure pam_pwquality module is enabled | password-auth" - when: "'password-auth:password' not in rhel8cis_pwquality_enabled.stdout" + when: "'password-auth:password' not in discovered_pwquality_enabled.stdout" ansible.builtin.lineinfile: backrefs: true insertafter: "{{ item.after | default (omit) }}" @@ -115,11 +115,11 @@ - name: "4.4.2.4 | AUDIT | Ensure pam_pwhistory module is enabled | Get current config" ansible.builtin.shell: authselect current | grep pwhistory changed_when: false - failed_when: rhel8cis_authselect_current.rc not in [ 0, 1 ] - register: rhel8cis_authselect_current + failed_when: discovered_authselect_current.rc not in [ 0, 1 ] + register: discovered_authselect_current - name: "4.4.2.4 | PATCH | Ensure pam_pwhistory module is enabled | enable feature" - when: rhel8cis_authselect_current.rc != 0 + when: discovered_authselect_current.rc != 0 ansible.builtin.shell: "authselect enable-feature with-pwhistory" - name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled" @@ -139,10 +139,10 @@ grep -P -- '\b(pam_unix\.so)\b' /etc/authselect/"$(head -1 /etc/authselect/authselect.conf)"/{system,password}-auth changed_when: false failed_when: rhel8cis_authselect_pam_unix.rc not in [ 0, 1 ] - register: rhel8cis_authselect_pam_unix + register: discovered_authselect_pam_unix - name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled | system-auth" - when: "'system-auth:password' not in rhel8cis_authselect_pam_unix.stdout" + when: "'system-auth:password' not in discovered_authselect_pam_unix.stdout" ansible.builtin.lineinfile: backrefs: true insertafter: "{{ item.after | default (omit) }}" @@ -155,7 +155,7 @@ - { regexp: '^(password\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', before: '^password.*pam_deny.so' } - name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled | password-auth" - when: "'password-auth:password' not in rhel8cis_authselect_pam_unix.stdout" + when: "'password-auth:password' not in discovered_authselect_pam_unix.stdout" ansible.builtin.lineinfile: backrefs: true insertafter: "{{ item.after | default (omit) }}" diff --git a/tasks/section_4/cis_4.4.3.1.x.yml b/tasks/section_4/cis_4.4.3.1.x.yml index dd45f4b9..062efcee 100644 --- a/tasks/section_4/cis_4.4.3.1.x.yml +++ b/tasks/section_4/cis_4.4.3.1.x.yml @@ -33,13 +33,13 @@ - rhel8cis_allow_authselect_updates ansible.builtin.shell: authselect current changed_when: false - failed_when: rhel8cis_authselect_current.rc not in [ 0, 1 ] - register: rhel8cis_authselect_current + failed_when: discovered_authselect_current.rc not in [ 0, 1 ] + register: discovered_authselect_current - name: "4.4.3.1.1 | PATCH | Ensure password failed attempts lockout is configured | authselect_files" when: - rhel8cis_allow_authselect_updates - - rhel8cis_authselect_current.rc != 0 + - discovered_authselect_current.rc != 0 ansible.builtin.replace: path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+deny\s*=\s*\S+(.*$) diff --git a/tasks/section_4/cis_4.4.3.3.x.yml b/tasks/section_4/cis_4.4.3.3.x.yml index b6957406..b321e3e1 100644 --- a/tasks/section_4/cis_4.4.3.3.x.yml +++ b/tasks/section_4/cis_4.4.3.3.x.yml @@ -97,13 +97,13 @@ ansible.builtin.shell: | grep -P -- '^\h*password\h+([^#\n\r]+)\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?use_authtok\ b' /etc/pam.d/{password,system}-auth changed_when: false - failed_when: rhel8cis_pwhistory_authtok.rc not in [ 0, 1 ] - register: rhel8cis_pwhistory_authtok + failed_when: discovered_pwhistory_authtok.rc not in [ 0, 1 ] + register: discovered_pwhistory_authtok - name: "4.4.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | authselect_files" when: - rhel8cis_allow_authselect_updates - - rhel8cis_pwhistory_authtok.rc != 0 + - discovered_pwhistory_authtok.rc != 0 notify: Update_authselect community.general.pamd: name: "{{ item }}-auth" diff --git a/tasks/section_4/cis_4.4.3.4.x.yml b/tasks/section_4/cis_4.4.3.4.x.yml index e6b8a128..d8f5489e 100644 --- a/tasks/section_4/cis_4.4.3.4.x.yml +++ b/tasks/section_4/cis_4.4.3.4.x.yml @@ -14,12 +14,12 @@ - name: "4.4.3.4.1 | PATCH | Ensure pam_unix does not include nullok | capture state" ansible.builtin.shell: grep -P -- '^\h*(auth|account|password|session)\h+(requisite|required|sufficient)\h+pam_unix\.so\b' /etc/pam.d/{password,system}-auth | grep -P -- '\bnullok\b' changed_when: false - failed_when: rhel8cis_pam_nullok.rc not in [ 0, 1 ] - register: rhel8cis_pam_nullok + failed_when: discovered_pam_nullok.rc not in [ 0, 1 ] + register: discovered_pam_nullok - name: "4.4.3.4.1 | PATCH | Ensure pam_unix does not include nullok | pam_files" when: - - rhel8cis_pam_nullok.stdout | length > 0 + - discovered_pam_nullok.stdout | length > 0 - not rhel8cis_allow_authselect_updates ansible.builtin.replace: path: "/etc/pam.d/{{ item }}-auth" @@ -31,8 +31,8 @@ - name: "4.4.3.4.1 | PATCH | Ensure pam_unix does not include nullok | update authselect" when: - - rhel8cis_pam_nullok is defined - - rhel8cis_pam_nullok.stdout | length > 0 + - discovered_pam_nullok is defined + - discovered_pam_nullok.stdout | length > 0 - rhel8cis_allow_authselect_updates notify: Update_authselect ansible.builtin.shell: authselect enable-feature without-nullok @@ -52,13 +52,13 @@ - name: "4.4.3.4.2 | AUDIT | Ensure pam_unix does not include remember | capture state" ansible.builtin.shell: grep -Pi '^\h*password\h+([^#\n\r]+\h+)?pam_unix\.so\b' /etc/pam.d/{password,system}-auth | grep -P '\bremember=\d\b' changed_when: false - failed_when: rhel8cis_pam_remember.rc not in [ 0, 1 ] - register: rhel8cis_pam_remember + failed_when: discovered_pam_remember.rc not in [ 0, 1 ] + register: discovered_pam_remember - name: "4.4.3.4.2 | PATCH | Ensure pam_unix does not include remember | pam_files" when: - - rhel8cis_pam_remember is defined - - rhel8cis_pam_remember | length > 0 + - discovered_pam_remember is defined + - discovered_pam_remember | length > 0 - not rhel8cis_allow_authselect_updates ansible.builtin.replace: path: "/etc/pam.d/{{ item }}-auth" @@ -70,8 +70,8 @@ - name: "4.4.3.4.2 | PATCH | Ensure pam_unix does not include remember | authconfig_files" when: - - rhel8cis_pam_remember is defined - - rhel8cis_pam_remember | length > 0 + - discovered_pam_remember is defined + - discovered_pam_remember | length > 0 - rhel8cis_allow_authselect_updates - "'example' not in rhel8cis_authselect['custom_profile_name']" notify: Update_authselect @@ -98,25 +98,25 @@ - name: "4.4.3.4.3 | AUDIT | Ensure pam_unix includes a strong password hashing algorithm | capture state" ansible.builtin.shell: grep -P -- '^\h*password\h+([^#\n\r]+)\h+pam_unix\.so\h+([^#\n\r]+\h+)?(sha512|yescrypt)\b' /etc/pam.d/{password,system}-auth | grep -v {{ rhel8cis_pam_pwhash }} changed_when: false - failed_when: rhel8cis_pam_pwhash.rc not in [ 0, 1 ] - register: rhel8cis_pam_pwhash + failed_when: discovered_hash_state.rc not in [ 0, 1 ] + register: discovered_hash_state - name: "4.4.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | pam_files" when: - - rhel8cis_pam_pwhash is defined - - rhel8cis_pam_pwhash | length > 0 + - discovered_hash_state is defined + - discovered_hash_state | length > 0 ansible.builtin.replace: path: "/etc/pam.d/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)(sha512|yescrypt)\s*=\s*\d+(.*$) - replace: \1\2\4 {{ rhel8cis_pam_pwhash }} + replace: \1\2\4 {{ discovered_hash_state.stdout }} loop: - password - system - name: "4.4.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | authselect_files" when: - - rhel8cis_pam_pwhash is defined - - rhel8cis_pam_pwhash | length > 0 + - discovered_hash_state is defined + - discovered_hash_state | length > 0 - rhel8cis_allow_authselect_updates - "'example' not in rhel8cis_authselect['custom_profile_name']" notify: Update_authselect @@ -143,32 +143,32 @@ - name: "4.4.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | capture state" ansible.builtin.shell: grep -P -- '^\h*password\h+([^#\n\r]+)\h+pam_unix\.so\h+([^#\n\r]+\h+)?use_authtok\b' /etc/pam.d/{password,system}-auth | grep -v use_authtok changed_when: false - failed_when: rhel8cis_pam_authtok.rc not in [ 0, 1 ] - register: rhel8cis_pam_authtok + failed_when: discovered_pam_authtok.rc not in [ 0, 1 ] + register: discovered_pam_authtok - name: "4.4.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | pam_files" when: - - rhel8cis_pam_authtok is defined - - rhel8cis_pam_authtok | length > 0 + - discovered_pam_authtok is defined + - discovered_pam_authtok | length > 0 ansible.builtin.replace: path: "/etc/pam.d/{{ item }}-auth" - regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\s+use_authtok\s*=\s*\S+(.*$) - replace: \1\2\3 use_authtok + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)\s+use_authtok(.*$) + replace: \1\3\4 use_authtok loop: - password - system - name: "4.4.3.4.4 | PATCH | Ensure password same consecutive characters is configured | authselect_files" when: - - rhel8cis_pam_authtok is defined - - rhel8cis_pam_authtok | length > 0 + - discovered_pam_authtok is defined + - discovered_pam_authtok | length > 0 - rhel8cis_allow_authselect_updates - "'example' not in rhel8cis_authselect['custom_profile_name']" notify: Update_authselect ansible.builtin.replace: path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" - regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\s+use_authtok\s*=\s*\S+(.*$) - replace: \1\2\3 use_authtok + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)\s+use_authtok(.*$) + replace: \1\3\4 use_authtok loop: - password - system diff --git a/tasks/section_4/cis_4.5.1.x.yml b/tasks/section_4/cis_4.5.1.x.yml index a1910fb4..49a3c3f8 100644 --- a/tasks/section_4/cis_4.5.1.x.yml +++ b/tasks/section_4/cis_4.5.1.x.yml @@ -35,8 +35,8 @@ - name: "4.5.1.2 | AUDIT | Ensure password expiration is 365 days or less | Capture accounts more than 365" ansible.builtin.shell: "grep -E '^[^:]+:[^!*]' /etc/shadow | awk -F':' '$5>{{ rhel8cis_pass['max_days'] }} { print $1 }'" changed_when: false - failed_when: rhel8cis_4_5_1_2_pass_max_expire.rc not in [ 0, 1 ] - register: rhel8cis_4_5_1_2_pass_max_expire + failed_when: discovered_pass_max_expire.rc not in [ 0, 1 ] + register: discovered_pass_max_expire - name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less | update login.defs" ansible.builtin.lineinfile: @@ -48,10 +48,10 @@ ansible.builtin.user: name: "{{ item }}" password_expire_max: "{{ rhel8cis_pass['max_days'] }}" - loop: "{{ rhel8cis_4_5_1_2_pass_max_expire.stdout_lines | default([]) }}" + loop: "{{ discovered_pass_max_expire.stdout_lines | default([]) }}" when: - - rhel8cis_4_5_1_2_set_max_expiry - - item not in rhel8cis_4_5_1_2_user_skip_list + - rhel8cis_set_max_expiry + - item not in rhel8cis_user_skip_list - name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less | Warning" block: @@ -59,16 +59,16 @@ ansible.builtin.debug: msg: | "Warning!! The following account are set beyond the expected expiration date: - {{ rhel8cis_4_5_1_2_pass_max_expire.stdout_lines | default([]) }}" + {{ rhel8cis_pass_max_expire.stdout_lines | default([]) }}" - name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less | set warning fact" ansible.builtin.import_tasks: warning_facts.yml vars: warn_control_id: '4.5.1.2' when: - - rhel8cis_4_5_1_2_pass_max_expire is defined - - rhel8cis_4_5_1_2_pass_max_expire.stdout | length > 0 - - not rhel8cis_4_5_1_2_set_max_expiry + - discovered_pass_max_expire is defined + - discovered_pass_max_expire.stdout | length > 0 + - not rhel8cis_set_max_expiry - name: "4.5.1.3 | PATCH | Ensure password expiration warning days is 7 or more" when: @@ -96,15 +96,15 @@ ansible.builtin.shell: | awk -F: '/^[^:\n\r]+:[^!*xX\n\r]/ {print $1}' /etc/shadow changed_when: false - failed_when: rhel8cis_users_warn_days.rc not in [ 0, 1 ] - register: rhel8cis_users_warn_days + failed_when: discovered_users_warn_days.rc not in [ 0, 1 ] + register: discovered_users_warn_days - name: "4.5.1.3 | PATCH | Ensure password expiration warning days is 7 or more | change users not matching req" when: - - rhel8cis_users_warn_days is defined - - rhel8cis_users_warn_days.stdout | length > 0 + - discovered_users_warn_days is defined + - discovered_users_warn_days.stdout | length > 0 ansible.builtin.shell: chage --warndays {{ rhel8cis_pass['warn_age'] }} {{ item }} - loop: "{{ rhel8cis_users_warn_days.stdout_lines }}" + loop: "{{ discovered_users_warn_days.stdout_lines }}" - name: "4.5.1.4 | PATCH | Ensure inactive password lock is 30 days or less" when: @@ -120,28 +120,28 @@ - name: "4.5.1.4 | AUDIT | Ensure inactive password lock is 30 days or less | capture default state" ansible.builtin.shell: useradd -D | grep INACTIVE changed_when: false - failed_when: rhel8cis_users_inactive_def.rc not in [ 0, 1 ] - register: rhel8cis_users_inactive_def + failed_when: discovered_users_inactive_def.rc not in [ 0, 1 ] + register: discovered_users_inactive_def - name: "4.5.1.4 | PATCH | Ensure inactive password lock is 30 days or less | change default" when: - - rhel8cis_users_inactive_def is defined - - "'30' not in rhel8cis_users_inactive_def.stdout" + - discovered_users_inactive_def is defined + - "'30' not in discovered_users_inactive_def.stdout" ansible.builtin.shell: useradd -D -f {{ rhel8cis_pass['inactive'] }} - name: "4.5.1.4 | AUDIT | Ensure inactive password lock is 30 days or less | capture users not matching" ansible.builtin.shell: | awk -F: '/^[^#:]+:[^!*:]*:[^:]*:[^:]*:[^:]*:[^:]*:(\s*|-1|3[1-9]|[4-9][0-9]|[1-9][0-9][0-9]+):[^:]*:[^:]*\s*$/ {print $1}' /etc/shadow changed_when: false - failed_when: rhel8cis_users_inactive.rc not in [ 0, 1 ] - register: rhel8cis_users_inactive + failed_when: discovered_users_inactive.rc not in [ 0, 1 ] + register: discovered_users_inactive - name: "4.5.1.4 | PATCH | Ensure inactive password lock is 30 days or less | change users not matching req" when: - - rhel8cis_users_inactive is defined - - rhel8cis_users_inactive.stdout | length > 0 + - discovered_users_inactive is defined + - discovered_users_inactive.stdout | length > 0 ansible.builtin.shell: chage --inactive {{ rhel8cis_pass['inactive'] }} {{ item }} - loop: "{{ rhel8cis_users_inactive.stdout_lines }}" + loop: "{{ discovered_users_inactive.stdout_lines }}" - name: "4.5.1.5 | PATCH | Ensure all users last password change date is in the past" when: @@ -159,13 +159,13 @@ - name: "4.5.1.5 | AUDIT | Ensure all users last password change date is in the past | capture default state" ansible.builtin.shell: useradd -D | grep INACTIVE changed_when: false - failed_when: rhel8cis_users_inactive_def.rc not in [ 0, 1 ] - register: rhel8cis_users_inactive_def + failed_when: discovered_users_inactive_default.rc not in [ 0, 1 ] + register: discovered_users_inactive_default - name: "4.5.1.5 | PATCH | Ensure all users last password change date is in the past | change default" when: - - rhel8cis_users_inactive_def is defined - - "'30' not in rhel8cis_users_inactive_def.stdout" + - discovered_users_inactive_default is defined + - "'30' not in discovered_users_inactive_default.stdout" ansible.builtin.shell: useradd -D -f {{ rhel8cis_pass['inactive'] }} - name: "4.5.1.5 | FACT | Ensure inactive password lock is 30 days or less | set fact days since_epoch" @@ -176,21 +176,21 @@ ansible.builtin.shell: | awk -F: '{ if ($3 > "{{ days_since_epoch }}") { print $1 } }' /etc/shadow changed_when: false - failed_when: rhel8cis_users_user_future.rc not in [ 0, 1 ] - register: rhel8cis_users_user_future + failed_when: discovered_users_user_future.rc not in [ 0, 1 ] + register: discovered_users_user_future - name: "4.5.1.5 | WARN | Ensure inactive password lock is 30 days or less | Warn Users in future" when: - - rhel8cis_users_user_future - - rhel8cis_users_user_future.stdout | length > 0 + - discovered_users_user_future is defined + - discovered_users_user_future.stdout | length > 0 ansible.builtin.debug: msg: - "Warning!! - The following users have passwords set in the future please investigate" - - "{{ rhel8cis_users_user_future.stdout_lines }}" + - "{{ discovered_users_user_future.stdout_lines }}" - name: "4.5.1.5 | WARN | Ensure inactive password lock is 30 days or less | Warn Users in future" when: - - rhel8cis_users_user_future + - rhel8cis_users_user_future is defined - rhel8cis_users_user_future.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml diff --git a/tasks/section_4/cis_4.5.2.x.yml b/tasks/section_4/cis_4.5.2.x.yml index 2a743fc9..8a44c2b0 100644 --- a/tasks/section_4/cis_4.5.2.x.yml +++ b/tasks/section_4/cis_4.5.2.x.yml @@ -58,7 +58,7 @@ - item.id != "shutdown" - item.id != "halt" - item.id != "nfsnobody" - - item.uid < rhel8cis_min_uid | int + - item.uid < discovered_min_uid.stdout | int - item.shell != " /bin/false" - item.shell != " /usr/sbin/nologin" ansible.builtin.user: @@ -75,7 +75,7 @@ - item.id != "shutdown" - item.id != "halt" - item.id != "nfsnobody" - - item.uid < rhel8cis_min_uid | int + - item.uid < discovered_min_uid.stdout | int - item.shell != " /bin/false" - item.shell != " /usr/sbin/nologin" ansible.builtin.user: diff --git a/tasks/section_5/cis_5.1.1.x.yml b/tasks/section_5/cis_5.1.1.x.yml index c0856616..ae568735 100644 --- a/tasks/section_5/cis_5.1.1.x.yml +++ b/tasks/section_5/cis_5.1.1.x.yml @@ -85,13 +85,13 @@ changed_when: false failed_when: false check_mode: false - register: rhel_09_5_1_1_5_audit + register: discovered_captured_rsyslog_conf - name: "5.1.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out" ansible.builtin.debug: msg: - "These are the current logging configurations for rsyslog, please review:" - - "{{ rhel_09_5_1_1_5_audit.stdout_lines }}" + - "{{ discovered_captured_rsyslog_conf.stdout_lines }}" - name: "5.1.1.5 | PATCH | Ensure logging is configured | mail.* log setting" when: rhel8cis_rsyslog_ansiblemanaged @@ -171,10 +171,10 @@ # target can be IP or FQDN *.* action(type="omfwd" target="{{ rhel8cis_remote_log_host }}" port="{{ rhel8cis_remote_log_port }}" protocol="{{ rhel8cis_remote_log_protocol }}" action.resumeRetryCount="{{ rhel8cis_remote_log_retrycount }}" queue.type="LinkedList" queue.size="{{ rhel8cis_remote_log_queuesize }}") insertafter: EOF - register: result + register: set_remote_syslog failed_when: - - result is failed - - result.rc != 257 + - set_remote_syslog is failed + - set_remote_syslog.rc != 257 - name: "5.1.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client" when: diff --git a/tasks/section_5/cis_5.1.2.x.yml b/tasks/section_5/cis_5.1.2.x.yml index 6f5e224c..6ee9aec5 100644 --- a/tasks/section_5/cis_5.1.2.x.yml +++ b/tasks/section_5/cis_5.1.2.x.yml @@ -103,20 +103,20 @@ ansible.builtin.shell: systemctl is-enabled systemd-journald.service changed_when: false failed_when: false - register: rhel8cis_5_1_2_2_status + register: discovered_journald_status - name: "5.1.2.2 | AUDIT | Ensure journald service is enabled | Alert on bad status" ansible.builtin.debug: msg: - "Warning!! The status of systemd-journald should be static and it is not. Please investigate" - when: "'static' not in rhel8cis_5_1_2_2_status.stdout" + when: "'static' not in discovered_journald_status.stdout" - name: "5.1.2.2 | AUDIT | Ensure journald service is enabled | Warn Count" ansible.builtin.import_tasks: file: warning_facts.yml vars: warn_control_id: '5.1.2.2' - when: "'static' not in rhel8cis_5_1_2_2_status.stdout" + when: "'static' not in discovered_journald_status.stdout" - name: "5.1.2.3 | PATCH | Ensure journald is configured to compress large log files" when: diff --git a/tasks/section_5/cis_5.1.3.yml b/tasks/section_5/cis_5.1.3.yml index 17d54768..673dd0d7 100644 --- a/tasks/section_5/cis_5.1.3.yml +++ b/tasks/section_5/cis_5.1.3.yml @@ -14,14 +14,14 @@ - name: "5.1.3 | AUDIT | Ensure logrotate is configured | Get logrotate settings" ansible.builtin.find: paths: /etc/logrotate.d/ - register: rhel8cis_log_rotate_conf + register: discovered_log_rotate_conf - name: "5.1.3 | PATCH | Ensure logrotate is configured | conf files" ansible.builtin.replace: path: "{{ item.path }}" regexp: '^(\s*)(daily|weekly|monthly|yearly)$' replace: "\\1{{ rhel8cis_logrotate }}" - loop: "{{ rhel8cis_log_rotate_conf.files }}" + loop: "{{ discovered_log_rotate_conf.files }}" - name: "5.1.3 | PATCH | Ensure logrotate is configured | logrotate.conf" ansible.builtin.replace: diff --git a/tasks/section_5/cis_5.1.4.yml b/tasks/section_5/cis_5.1.4.yml index f646d749..bd20b407 100644 --- a/tasks/section_5/cis_5.1.4.yml +++ b/tasks/section_5/cis_5.1.4.yml @@ -16,20 +16,20 @@ ansible.builtin.shell: find /var/log/ -type f -perm /g+wx,o+rwx -exec ls {} \; changed_when: false failed_when: false - register: rhel8cis_5_1_4_logfiles + register: discovered_logfiles - name: "5.1.4 | AUDIT | Ensure permissions on all logfiles are configured | set_fact" ansible.builtin.set_fact: - rhel8cis_4_2_3_logfiles_flattened: "{{ rhel8cis_5_1_4_logfiles | json_query('stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] + discovered_logfiles_flattened: "{{ discovered_logfiles | json_query('stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] when: - - rhel8cis_5_1_4_logfiles.stdout_lines | length > 0 - - rhel8cis_5_1_4_logfiles is defined + - discovered_logfiles.stdout_lines | length > 0 + - discovered_logfiles is defined - name: "5.1.4 | PATCH | Ensure permissions on all logfiles are configured | change permissions" ansible.builtin.file: path: "{{ item }}" mode: '0640' - loop: "{{ rhel8cis_5_1_4_logfiles_flattened }}" + loop: "{{ discovered_logfiles_flattened }}" when: - rhel8cis_5_1_4_logfiles_flattened is defined - item != "/var/log/btmp" diff --git a/tasks/section_5/cis_5.2.1.x.yml b/tasks/section_5/cis_5.2.1.x.yml index 13caa3f5..550ee270 100644 --- a/tasks/section_5/cis_5.2.1.x.yml +++ b/tasks/section_5/cis_5.2.1.x.yml @@ -45,21 +45,21 @@ changed_when: false failed_when: false check_mode: false - register: rhel8cis_5_2_1_2_grub_cmdline_linux + register: discovered_auditd_grub_cmdline_linux - name: "5.2.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Replace existing setting" - when: "'audit=' in rhel8cis_5_2_1_2_grub_cmdline_linux.stdout" + when: "'audit=' in discovered_auditd_grub_cmdline_linux.stdout" ansible.builtin.replace: path: /etc/default/grub regexp: 'audit=.' replace: 'audit=1' - name: "5.2.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Add audit setting if missing" - when: "'audit=' not in rhel8cis_5_2_1_2_grub_cmdline_linux.stdout" + when: "'audit=' not in discovered_auditd_grub_cmdline_linux.stdout" ansible.builtin.lineinfile: path: /etc/default/grub regexp: '^GRUB_CMDLINE_LINUX=' - line: '{{ rhel8cis_5_2_1_2_grub_cmdline_linux.stdout }} audit=1"' + line: '{{ discovered_auditd_grub_cmdline_linux.stdout }} audit=1"' - name: "5.2.1.3 | PATCH | Ensure audit_backlog_limit is sufficient" when: @@ -82,21 +82,21 @@ changed_when: false failed_when: false check_mode: false - register: rhel8cis_5_2_1_3_grub_cmdline_linux + register: discovered_backlog_grub_cmdline_linux - name: "5.2.1.3 | PATCH | Ensure audit_backlog_limit is sufficient | Replace existing setting" ansible.builtin.replace: path: /etc/default/grub regexp: 'audit_backlog_limit=\d+' replace: 'audit_backlog_limit={{ rhel8cis_audit_back_log_limit }}' - when: "'audit_backlog_limit=' in rhel8cis_5_2_1_3_grub_cmdline_linux.stdout" + when: "'audit_backlog_limit=' in discovered_backlog_grub_cmdline_linux.stdout" - name: "5.2.1.3 | PATCH | Ensure audit_backlog_limit is sufficient | Add audit_backlog_limit setting if missing" ansible.builtin.lineinfile: path: /etc/default/grub regexp: '^GRUB_CMDLINE_LINUX=' - line: '{{ rhel8cis_5_2_1_3_grub_cmdline_linux.stdout }} audit_backlog_limit={{ rhel8cis_audit_back_log_limit }}"' - when: "'audit_backlog_limit=' not in rhel8cis_5_2_1_3_grub_cmdline_linux.stdout" + line: '{{ discovered_backlog_grub_cmdline_linux.stdout }} audit_backlog_limit={{ rhel8cis_audit_back_log_limit }}"' + when: "'audit_backlog_limit=' not in discovered_backlog_grub_cmdline_linux.stdout" - name: "5.2.1.4 | PATCH | Ensure auditd service is enabled" when: diff --git a/tasks/section_5/cis_5.2.3.x.yml b/tasks/section_5/cis_5.2.3.x.yml index 6875114b..8e24f22a 100644 --- a/tasks/section_5/cis_5.2.3.x.yml +++ b/tasks/section_5/cis_5.2.3.x.yml @@ -82,7 +82,7 @@ changed_when: false failed_when: false check_mode: false - register: priv_procs + register: discovered_privilege_procs - name: "5.2.3.6 | PATCH | Ensure use of privileged commands is collected" ansible.builtin.set_fact: diff --git a/tasks/section_5/cis_5.2.4.x.yml b/tasks/section_5/cis_5.2.4.x.yml index 4e00f6c1..e78a7ff1 100644 --- a/tasks/section_5/cis_5.2.4.x.yml +++ b/tasks/section_5/cis_5.2.4.x.yml @@ -9,17 +9,10 @@ - patch - auditd - rule_5.2.4.1 - block: - - name: "5.2.4.1 | AUDIT | Ensure the audit log directory is 0750 or more restrictive | get current permissions" - ansible.builtin.stat: - path: "{{ audit_discovered_logfile.stdout | dirname }}" - register: auditlog_dir - - - name: "5.2.4.1 | PATCH | Ensure the audit log directory is 0750 or more restrictive | set" - ansible.builtin.file: - path: "{{ audit_discovered_logfile.stdout | dirname }}" - state: directory - mode: g-w,o-rwx + ansible.builtin.file: + path: "{{ discovered_audit_logfile.stdout | dirname }}" + state: directory + mode: g-w,o-rwx - name: | "5.2.4.2 | PATCH | Ensure audit log files are mode 0640 or less permissive" @@ -38,24 +31,19 @@ - rule_5.2.4.3 - rule_5.2.4.4 block: - - name: "5.2.4.2 | AUDIT | Ensure audit log files are mode 0640 or less permissive | discover file" - ansible.builtin.shell: grep ^log_file /etc/audit/auditd.conf | awk '{ print $NF }' - changed_when: false - register: audit_discovered_logfile - - name: "5.2.4.2 | AUDIT | Ensure audit log files are mode 0640 or less permissive | stat file" ansible.builtin.stat: - path: "{{ audit_discovered_logfile.stdout }}" + path: "{{ discovered_audit_logfile.stdout }}" changed_when: false - register: auditd_logfile + register: discovered_auditlog_info - name: | "5.2.4.2 | PATCH | Ensure audit log files are mode 0640 or less permissive" "5.2.4.3 | PATCH | Ensure only authorized users own audit log files" "5.2.4.4 | PATCH | Ensure only authorized groups are assigned ownership of audit log files" ansible.builtin.file: - path: "{{ audit_discovered_logfile.stdout }}" - mode: "{% if auditd_logfile.stat.mode != '0600' %}0640{% endif %}" + path: "{{ discovered_audit_logfile.stdout }}" + mode: "{% if discovered_auditlog_info.stat.mode != '0600' %}0640{% endif %}" owner: root group: root @@ -71,7 +59,7 @@ ansible.builtin.file: path: "{{ item.path }}" mode: g-wx,o-rwx - loop: "{{ auditd_conf_files.files }}" + loop: "{{ discovered_auditd_conf_files.files }}" loop_control: label: "{{ item.path }}" @@ -87,7 +75,7 @@ ansible.builtin.file: path: "{{ item.path }}" owner: root - loop: "{{ auditd_conf_files.files }}" + loop: "{{ discovered_auditd_conf_files.files }}" loop_control: label: "{{ item.path }}" @@ -103,7 +91,7 @@ ansible.builtin.file: path: "{{ item.path }}" group: root - loop: "{{ auditd_conf_files.files }}" + loop: "{{ discovered_auditd_conf_files.files }}" loop_control: label: "{{ item.path }}" @@ -120,7 +108,7 @@ - name: "5.2.4.8 | AUDIT | Get audit binary file stat | get current mode" ansible.builtin.stat: path: "{{ item }}" - register: "audit_bins" + register: discovered_audit_bins_mode loop: - /sbin/auditctl - /sbin/aureport @@ -133,7 +121,7 @@ ansible.builtin.file: path: "{{ item.item }}" mode: g-w,o-w - loop: "{{ audit_bins.results }}" + loop: "{{ discovered_audit_bins_mode.results }}" loop_control: label: "{{ item.item }}" diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 201012eb..6e4d166a 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -201,17 +201,17 @@ ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -0002 failed_when: false changed_when: false - register: rhel_08_6_1_11_perms_results + register: discovered_perms_results - name: "6.1.11 | PATCH | Adjust world-writable files if they exist (Configurable)" when: - - rhel_08_6_1_11_perms_results.stdout_lines is defined + - discovered_perms_results.stdout_lines is defined - rhel8cis_no_world_write_adjust ansible.builtin.file: path: '{{ item }}' mode: o-w state: touch - with_items: "{{ rhel_08_6_1_11_perms_results.stdout_lines }}" + with_items: "{{ discovered_perms_results.stdout_lines }}" - name: "6.1.11 | PATCH | Ensure world writable files and directories are secured | sticky bit set on world-writable directories" ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -0002 2>/dev/null | xargs chmod a+t @@ -220,14 +220,14 @@ - name: "6.1.11 | AUDIT | Ensure world writable files and directories are secured | Warning" when: - - rhel_08_6_1_11_perms_results.stdout_lines is defined + - discovered_perms_results.stdout_lines is defined - not rhel8cis_no_world_write_adjust ansible.builtin.debug: msg: "Warning!! - WorldWritable files have been found" - name: "6.1.11 | AUDIT | Ensure world writable files and directories are secured | Warn Count" when: - - rhel_08_6_1_11_perms_results.stdout_lines is defined + - discovered_perms_results.stdout_lines is defined - not rhel8cis_no_world_write_adjust ansible.builtin.import_tasks: file: warning_facts.yml @@ -253,7 +253,7 @@ changed_when: false failed_when: false check_mode: false - register: rhel8cis_6_1_12_ungrouped_items + register: discovered_ungrouped_items with_items: - "{{ ansible_facts.mounts }}" loop_control: @@ -261,32 +261,32 @@ - name: "6.1.12 | AUDIT | Ensure no ungrouped files or directories exist | Flatten ungrouped_items results for easier use" ansible.builtin.set_fact: - rhel8cis_6_1_12_ungrouped_items_flatten: "{{ rhel8cis_6_1_12_ungrouped_items.results | map(attribute='stdout_lines') | flatten }}" + discovered_ungrouped_items_flatten: "{{ discovered_ungrouped_items.results | map(attribute='stdout_lines') | flatten }}" - name: "6.1.12 | AUDIT | Ensure no ungrouped files or directories exist | Alert on ungrouped files and directories" when: - not rhel8cis_ungrouped_adjust - - rhel8cis_6_1_12_ungrouped_items_flatten | length > 0 + - discovered_ungrouped_items_flatten | length > 0 ansible.builtin.debug: msg: - "Warning!! You have ungrouped files/directories and are configured to not auto-remediate for this task" - "Please review the files/directories below and assign a group" - - "{{ rhel8cis_6_1_12_ungrouped_items_flatten }}" + - "{{ discovered_ungrouped_items_flatten }}" - name: "6.1.12 | PATCH | Ensure no ungrouped files or directories exist | Set ungrouped files/directories to configured group" when: - rhel8cis_ungrouped_adjust - - rhel8cis_6_1_12_ungrouped_items_flatten | length > 0 + - discovered_ungrouped_items_flatten | length > 0 ansible.builtin.file: path: "{{ item }}" group: "{{ rhel8cis_ungrouped_group }}" loop: - - "{{ rhel8cis_6_1_12_ungrouped_items_flatten }}" + - "{{ discovered_ungrouped_items_flatten }}" - name: "6.1.12 | AUDIT | Ensure no ungrouped files or directories exist | Warn Count" when: - rhel8cis_ungrouped_adjust - - rhel8cis_6_1_12_ungrouped_items_flatten | length > 0 + - discovered_ungrouped_items_flatten | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml @@ -309,7 +309,7 @@ changed_when: false failed_when: false check_mode: false - register: rhel8cis_6_1_13_suid_executables + register: discovered_suid_executables loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.mount }}" @@ -319,63 +319,63 @@ changed_when: false failed_when: false check_mode: false - register: rhel8cis_6_1_13_sgid_executables + register: discovered_sgid_executables loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.mount }}" - name: "6.1.13 | AUDIT | Ensure SUID and SGID files are reviewed | Flatten suid_executables results for easier use" ansible.builtin.set_fact: - rhel8cis_6_1_13_suid_executables_flatten: "{{ rhel8cis_6_1_13_suid_executables.results | map(attribute='stdout_lines') | flatten }}" + discovered_suid_executables_flatten: "{{ discovered_suid_executables.results | map(attribute='stdout_lines') | flatten }}" - name: "6.1.13 | AUDIT | Ensure SUID and SGID files are reviewed | Set fact SGID executables" ansible.builtin.set_fact: - rhel8cis_6_1_13_sgid_executables_flatten: "{{ rhel8cis_6_1_13_sgid_executables.results | map(attribute='stdout_lines') | flatten }}" + discovered_sgid_executables_flatten: "{{ discovered_sgid_executables.results | map(attribute='stdout_lines') | flatten }}" - name: "6.1.13 | PATCH | Ensure SUID and SGID files are reviewed | Remove SUID bit" when: - rhel8cis_suid_adjust - - rhel8cis_6_1_13_suid_executables_flatten | length > 0 + - discovered_suid_executables_flatten | length > 0 ansible.builtin.file: path: "{{ item }}" mode: 'u-s' loop: - - "{{ rhel8cis_6_1_13_suid_executables_flatten }}" + - "{{ discovered_suid_executables_flatten }}" - name: "6.1.13 | PATCH | Audit SGID executables | Remove SGID bit" ansible.builtin.file: path: "{{ item }}" mode: 'g-s' with_items: - - "{{ rhel8cis_6_1_13_sgid_executables_flatten }}" + - "{{ discovered_sgid_executables_flatten }}" when: - rhel8cis_sgid_adjust - - rhel8cis_6_1_13_sgid_executables_flatten | length > 0 + - discovered_sgid_executables_flatten | length > 0 - name: "6.1.13 | WARN | Ensure SUID and SGID files are reviewed | Alert SUID executables exist" when: - - rhel8cis_6_1_13_suid_executables_flatten | length > 0 + - discovered_suid_executables_flatten | length > 0 - not rhel8cis_suid_adjust ansible.builtin.debug: msg: - "Warning!! You have SUID executables" - "The files are listed below, please confirm the integrity of these binaries" - - "{{ rhel8cis_6_1_13_suid_executables_flatten }}" + - "{{ discovered_suid_executables_flatten }}" - name: "6.1.13 | WARN | Ensure SUID and SGID files are reviewed | Alert SGID executables exist" when: - - rhel8cis_6_1_13_sgid_executables_flatten | length > 0 + - discovered_sgid_executables_flatten | length > 0 - not rhel8cis_sgid_adjust ansible.builtin.debug: msg: - "Warning!! You have SGID executables" - "The files are listed below, please review the integrity of these binaries" - - "{{ rhel8cis_6_1_13_sgid_executables_flatten }}" + - "{{ discovered_sgid_executables_flatten }}" - name: "6.1.13 | WARN | Ensure SUID and SGID files are reviewed | Warn Count" when: - - (rhel8cis_6_1_13_suid_executables_flatten | length > 0 and not rhel8cis_suid_adjust) or - (rhel8cis_6_1_13_sgid_executables_flatten | length > 0 and not rhel8cis_sgid_adjust) + - (discovered_suid_executables_flatten | length > 0 and not rhel8cis_suid_adjust) or + (discovered_sgid_executables_flatten | length > 0 and not rhel8cis_sgid_adjust) ansible.builtin.import_tasks: file: warning_facts.yml @@ -404,26 +404,26 @@ ansible.builtin.shell: rpm -Va --nomtime --nosize --nomd5 --nolinkto changed_when: false failed_when: false - register: rhel8cis_6_1_14_packages_rpm + register: discovered_packages_rpm - name: "6.1.14 | AUDIT | Audit system file permissions | Create list and warning" block: - name: "6.1.14 | AUDIT | Audit system file permissions | Add file discrepancy list to system" ansible.builtin.copy: dest: "{{ rhel8cis_rpm_audit_file }}" # noqa template-instead-of-copy - content: "{{ rhel8cis_6_1_14_packages_rpm.stdout }}" + content: "{{ discovered_packages_rpm.stdout }}" owner: root group: root mode: '0644' - name: "6.1.14 | AUDIT | Audit system file permissions | Message out alert for package descrepancies" - when: rhel8cis_6_1_14_packages_rpm.stdout | length > 0 + when: discovered_packages_rpm.stdout | length > 0 ansible.builtin.debug: msg: | "Warning!! We have discovered package discrepancies. The file list can be found in {{ rhel8cis_rpm_audit_file }}" - name: "6.1.14 | AUDIT | Audit system file permissions | Warn Count" - when: rhel8cis_6_1_14_packages_rpm.stdout | length > 0 + when: discovered_packages_rpm.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml diff --git a/tasks/section_6/cis_6.2.x.yml b/tasks/section_6/cis_6.2.x.yml index ffecad2f..6a33eb4e 100644 --- a/tasks/section_6/cis_6.2.x.yml +++ b/tasks/section_6/cis_6.2.x.yml @@ -18,17 +18,17 @@ ansible.builtin.shell: awk -F':' '($2 != "x" ) { print $1}' /etc/passwd changed_when: false failed_when: false - register: rhel8cis_6_2_1_nonshadowed_users + register: discovered_nonshadowed_users - name: "6.2.1 | AUDIT | Ensure accounts in /etc/passwd use shadowed passwords | Warn on findings" - when: rhel8cis_6_2_1_nonshadowed_users.stdout | length > 0 + when: discovered_nonshadowed_users.stdout | length > 0 ansible.builtin.debug: msg: - "Warning!! You have users that are not using a shadowed password. Please convert the below accounts to use a shadowed password" - - "{{ rhel8cis_6_2_1_nonshadowed_users.stdout_lines }}" + - "{{ discovered_nonshadowed_users.stdout_lines }}" - name: "6.2.1 | WARN | Ensure accounts in /etc/passwd use shadowed passwords | warn_count" - when: rhel8cis_6_2_1_nonshadowed_users.stdout | length > 0 + when: discovered_nonshadowed_users.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml @@ -49,15 +49,15 @@ ansible.builtin.shell: awk -F":" '($2 == "" ) { print $1 }' /etc/shadow changed_when: false check_mode: false - register: rhel8cis_6_2_2_empty_password_acct + register: discovered_empty_password_acct - name: "6.2.2 | PATCH | Ensure /etc/shadow password fields are not empty | Lock users with empty password" - when: rhel8cis_6_2_2_empty_password_acct.stdout | length > 0 + when: discovered_empty_password_acct.stdout | length > 0 ansible.builtin.user: name: "{{ item }}" password_lock: true loop: - - "{{ rhel8cis_6_2_2_empty_password_acct.stdout_lines }}" + - "{{ discovered_empty_password_acct.stdout_lines }}" - name: "6.2.3 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group" when: @@ -82,15 +82,15 @@ changed_when: false failed_when: false check_mode: false - register: rhel8cis_6_2_3_passwd_gid_check + register: discovered_passwd_gid_check - name: "6.2.3 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Print warning about users with invalid GIDs missing GID entries in /etc/group" - when: rhel8cis_6_2_3_passwd_gid_check.stdout | length > 0 + when: discovered_passwd_gid_check.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following users have non-existent GIDs (Groups): {{ rhel8cis_6_2_3_passwd_gid_check.stdout_lines | join (', ') }}" + msg: "Warning!! The following users have non-existent GIDs (Groups): {{ discovered_passwd_gid_check.stdout_lines | join (', ') }}" - name: "6.2.3 | WARN | Ensure all groups in /etc/passwd exist in /etc/group | warn_count" - when: rhel8cis_6_2_3_passwd_gid_check.stdout | length > 0 + when: discovered_passwd_gid_check.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml @@ -117,15 +117,15 @@ changed_when: false failed_when: false check_mode: false - register: rhel8cis_6_2_4_user_uid_check + register: discovered_user_uid_check - name: "6.2.4 | AUDIT | Ensure no duplicate UIDs exist | Print warning about users with duplicate UIDs" - when: rhel8cis_6_2_4_user_uid_check.stdout | length > 0 + when: discovered_user_uid_check.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following users have UIDs that are duplicates: {{ rhel8cis_6_2_4_user_uid_check.stdout_lines }}" + msg: "Warning!! The following users have UIDs that are duplicates: {{ discovered_user_uid_check.stdout_lines }}" - name: "6.2.4 | AUDIT | Ensure no duplicate UIDs exist | Set warning count" - when: rhel8cis_6_2_4_user_uid_check.stdout | length > 0 + when: discovered_user_uid_check.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml @@ -152,15 +152,15 @@ changed_when: false failed_when: false check_mode: false - register: rhel8cis_6_2_5_user_user_check + register: discovered_user_gid_check - name: "6.2.5 | AUDIT | Ensure no duplicate GIDs exist | Print warning about users with duplicate GIDs" - when: rhel8cis_6_2_5_user_user_check.stdout | length > 0 + when: discovered_user_gid_check.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following groups have duplicate GIDs: {{ rhel8cis_6_2_5_user_user_check.stdout_lines }}" + msg: "Warning!! The following groups have duplicate GIDs: {{ discovered_user_gid_check.stdout_lines }}" - name: "6.2.5 | AUDIT | Ensure no duplicate GIDs exist | Set warning count" - when: rhel8cis_6_2_5_user_user_check.stdout | length > 0 + when: discovered_user_gid_check.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml @@ -187,15 +187,15 @@ changed_when: false failed_when: false check_mode: false - register: rhel8cis_6_2_6_username_check + register: discovered_username_check - name: "6.2.6 | WARN | Ensure no duplicate user names exist | Print warning about users with duplicate User Names" - when: rhel8cis_6_2_6_username_check.stdout | length > 0 + when: discovered_username_check.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following user names are duplicates: {{ rhel8cis_6_2_6_user_username_check.stdout_lines }}" + msg: "Warning!! The following user names are duplicates: {{ discovered_user_username_check.stdout_lines }}" - name: "6.2.6 | WARN | Ensure no duplicate user names exist | Set warning count" - when: rhel8cis_6_2_6_username_check.stdout | length > 0 + when: discovered_username_check.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml @@ -222,15 +222,15 @@ changed_when: false failed_when: false check_mode: false - register: rhel8cis_6_2_7_group_check + register: discovered_group_check - name: "6.2.7 | AUDIT | Ensure no duplicate group names exist | Print warning about users with duplicate group names" - when: rhel8cis_6_2_7_group_check.stdout | length > 0 + when: discovered_group_check.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following group names are duplicates: {{ rhel8cis_6_2_7_group_group_check.stdout_lines }}" + msg: "Warning!! The following group names are duplicates: {{ discovered_group_group_check.stdout_lines }}" - name: "6.2.7 | AUDIT | Ensure no duplicate group names exist | Set warning count" - when: rhel8cis_6_2_7_group_check.stdout | length > 0 + when: discovered_group_check.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml @@ -252,36 +252,36 @@ - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Get root paths" ansible.builtin.shell: sudo -Hiu root env | grep '^PATH' | cut -d= -f2 changed_when: false - register: rhel8cis_6_2_8_root_paths + register: discovered_root_paths - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Get root paths" ansible.builtin.shell: sudo -Hiu root env | grep '^PATH' | cut -d= -f2 | tr ":" "\n" changed_when: false - register: rhel8cis_6_2_8_root_paths_split + register: discovered_root_paths_split - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Set fact" ansible.builtin.set_fact: - root_paths: "{{ rhel8cis_6_2_8_root_paths.stdout }}" + root_paths: "{{ discovered_root_paths.stdout }}" - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Check for empty dirs" ansible.builtin.shell: 'echo {{ root_paths }} | grep -q "::" && echo "roots path contains a empty directory (::)"' changed_when: false - failed_when: root_path_empty_dir.rc not in [ 0, 1 ] - register: root_path_empty_dir + failed_when: discovered_root_path_empty_dir.rc not in [ 0, 1 ] + register: discovered_root_path_empty_dir - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Check for trailing ':'" ansible.builtin.shell: '{{ root_paths }} | cut -d= -f2 | grep -q ":$" && echo "roots path contains a trailing (:)"' changed_when: false - failed_when: root_path_trailing_colon.rc not in [ 0, 1 ] - register: root_path_trailing_colon + failed_when: discovered_root_path_trailing_colon.rc not in [ 0, 1 ] + register: discovered_root_path_trailing_colon - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Check for owner and permissions" block: - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Check for owner and permissions" ansible.builtin.stat: path: "{{ item }}" - register: root_path_perms - loop: "{{ rhel8cis_6_2_8_root_paths_split.stdout_lines }}" + register: discovered_root_path_perms + loop: "{{ discovered_root_paths_split.stdout_lines }}" - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Set permissions" when: @@ -296,13 +296,13 @@ group: root mode: '0755' follow: false - loop: "{{ root_path_perms.results }}" + loop: "{{ discovered_root_path_perms.results }}" loop_control: label: "{{ item }}" - name: "6.2.9 | PATCH | Ensure root is the only UID 0 account" when: - - rhel8cis_uid_zero_accounts_except_root.rc + - discovered_uid_zero_accounts_except_root.rc - rhel8cis_rule_6_2_9 tags: - level1-server @@ -319,7 +319,7 @@ ansible.builtin.shell: passwd -l {{ item }} changed_when: false failed_when: false - loop: "{{ rhel8cis_uid_zero_accounts_except_root.stdout_lines }}" + loop: "{{ discovered_uid_zero_accounts_except_root.stdout_lines }}" - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist" when: @@ -342,29 +342,29 @@ state: directory owner: "{{ item.id }}" group: "{{ item.gid }}" - register: rhel8cis_6_2_10_home_dir - loop: "{{ rhel8cis_passwd | selectattr('uid', '>=', rhel8cis_min_uid.stdout | int ) | selectattr('uid', '<=', rhel8cis_max_uid.stdout | int ) | list }}" + register: discovered_home_dirs + loop: "{{ rhel8cis_passwd | selectattr('uid', '>=', discovered_min_uid.stdout | int ) | selectattr('uid', '<=', discovered_max_uid.stdout | int ) | list }}" loop_control: label: "{{ item.id }}" - name: "6.2.10 | AUDIT | Ensure local interactive user home directories exist | Get perms stat" ansible.builtin.stat: path: "{{ item }}" - register: rhel_09_6_2_10_home_dir_perms - loop: "{{ interactive_users_home.stdout_lines }}" + register: discovered_home_dir_perms + loop: "{{ discovered_interactive_users_home.stdout_lines }}" - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Set perms if needed" ansible.builtin.file: path: "{{ item.stat.path }}" state: directory mode: g-w,o-rwx - loop: "{{ rhel_09_6_2_10_home_dir_perms.results }}" + loop: "{{ discovered_home_dir_perms.results }}" loop_control: label: "{{ item }}" - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Own their home directories" when: - - item.uid >= rhel8cis_min_uid | int + - item.uid >= discovered_min_uid.stdout | int - item.id != 'nobody' - (item.id != 'tss' and item.dir != '/dev/null') - item.shell != '/sbin/nologin' @@ -374,7 +374,7 @@ path: "{{ item.dir }}" owner: "{{ item.id }}" state: directory - loop: "{{ rhel8cis_passwd | selectattr('uid', '>=', rhel8cis_min_uid.stdout | int ) | selectattr('uid', '<=', rhel8cis_max_uid.stdout | int ) | list }}" + loop: "{{ rhel8cis_passwd | selectattr('uid', '>=', discovered_min_uid.stdout | int ) | selectattr('uid', '<=', discovered_max_uid.stdout | int ) | list }}" loop_control: label: "{{ item.id }}" @@ -386,7 +386,7 @@ etype: group permissions: rx state: present - loop: "{{ interactive_users_home.stdout_lines }}" + loop: "{{ discovered_interactive_users_home.stdout_lines }}" when: not system_is_container - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Set other ACL" @@ -396,7 +396,7 @@ etype: other permissions: 0 state: present - loop: "{{ interactive_users_home.stdout_lines }}" + loop: "{{ discovered_interactive_users_home.stdout_lines }}" when: not system_is_container - name: "6.2.11 | PATCH | Ensure local interactive user dot files access is configured" @@ -421,13 +421,13 @@ - name: "6.2.11 | AUDIT | Ensure local interactive user dot files access is configured | Check for files" ansible.builtin.shell: find /home/ -name "\.*" -perm /g+w,o+w changed_when: false - failed_when: rhel8cis_6_2_11_audit.rc not in [ 0, 1 ] + failed_when: discovered_dot_files.rc not in [ 0, 1 ] check_mode: false - register: rhel8cis_6_2_11_audit + register: discovered_dot_files - name: "6.2.11 | AUDIT | Ensure local interactive user dot files access is configured | Warning on files found" when: - - rhel8cis_6_2_11_audit.stdout | length > 0 + - discovered_dot_files.stdout | length > 0 - rhel8cis_dotperm_ansiblemanaged ansible.builtin.debug: @@ -436,7 +436,7 @@ - name: "6.2.11 | PATCH | Ensure local interactive user dot files access is configured | Set warning count" when: - - rhel8cis_6_2_11_audit.stdout | length > 0 + - discovered_dot_files.stdout | length > 0 - rhel8cis_dotperm_ansiblemanaged ansible.builtin.import_tasks: @@ -444,10 +444,10 @@ - name: "6.2.11 | PATCH | Ensure local interactive user dot files access is configured | Changes files if configured" when: - - rhel8cis_6_2_11_audit.stdout | length > 0 + - discovered_dot_files.stdout | length > 0 - rhel8cis_dotperm_ansiblemanaged ansible.builtin.file: path: '{{ item }}' mode: go-w - with_items: "{{ rhel8cis_6_2_11_audit.stdout_lines }}" + with_items: "{{ discovered_dot_files.stdout_lines }}" diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index ae15877d..ede69166 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -27,7 +27,7 @@ -w /etc/sysconfig/network-scripts/ -p wa -k system-locale {% endif %} {% if rhel8cis_rule_5_2_3_6 %} -{% for proc in priv_procs.stdout_lines -%} +{% for proc in discovered_privilege_procs.stdout_lines -%} -a always,exit -F path={{ proc }} -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k privileged {% endfor %} {% endif %} diff --git a/vars/is_container.yml b/vars/is_container.yml index 67039fd3..83f929b9 100644 --- a/vars/is_container.yml +++ b/vars/is_container.yml @@ -1,5 +1,9 @@ --- +## Example file that maybe used for containers +## This is still dependant in the container usage +## Please confirm before running that it is suitable for your environment + rhel8cis_section1: true rhel8cis_section2: true rhel8cis_section3: true @@ -7,8 +11,6 @@ rhel8cis_section4: true rhel8cis_section5: true rhel8cis_section6: true -rhel8cis_firewall: none - # These variables correspond with the CIS rule IDs or paragraph numbers defined in # the CIS benchmark documents. # PLEASE NOTE: These work in coordination with the section # group variables and tags. @@ -17,70 +19,88 @@ rhel8cis_firewall: none rhel8cis_rule_1_1_1_1: true rhel8cis_rule_1_1_1_2: true rhel8cis_rule_1_1_1_3: true -rhel8cis_rule_1_1_2_1: false -rhel8cis_rule_1_1_2_2: false -rhel8cis_rule_1_1_2_3: false -rhel8cis_rule_1_1_2_4: false -rhel8cis_rule_1_1_3_1: false -rhel8cis_rule_1_1_3_2: false -rhel8cis_rule_1_1_3_3: false -rhel8cis_rule_1_1_3_4: false -rhel8cis_rule_1_1_4_1: false -rhel8cis_rule_1_1_4_2: false -rhel8cis_rule_1_1_4_3: false -rhel8cis_rule_1_1_4_4: false -rhel8cis_rule_1_1_5_1: false -rhel8cis_rule_1_1_5_2: false -rhel8cis_rule_1_1_5_3: false -rhel8cis_rule_1_1_5_4: false -rhel8cis_rule_1_1_6_1: false -rhel8cis_rule_1_1_6_2: false -rhel8cis_rule_1_1_6_3: false -rhel8cis_rule_1_1_6_4: false -rhel8cis_rule_1_1_7_1: false -rhel8cis_rule_1_1_7_2: false -rhel8cis_rule_1_1_7_3: false -rhel8cis_rule_1_1_7_4: false -rhel8cis_rule_1_1_7_5: false -rhel8cis_rule_1_1_8_1: false -rhel8cis_rule_1_1_8_2: false -rhel8cis_rule_1_1_8_3: false -rhel8cis_rule_1_1_9: false -rhel8cis_rule_1_1_10: false -rhel8cis_rule_1_2_1: false +rhel8cis_rule_1_1_1_4: true +rhel8cis_rule_1_1_1_5: true +rhel8cis_rule_1_1_1_6: true +rhel8cis_rule_1_1_1_7: true +rhel8cis_rule_1_1_1_8: true + +# /tmp +rhel8cis_rule_1_1_2_1_1: false +rhel8cis_rule_1_1_2_1_2: false +rhel8cis_rule_1_1_2_1_3: false +rhel8cis_rule_1_1_2_1_4: false + +# /dev/shm +rhel8cis_rule_1_1_2_2_1: false +rhel8cis_rule_1_1_2_2_2: false +rhel8cis_rule_1_1_2_2_3: false +rhel8cis_rule_1_1_2_2_4: false + +# /home +rhel8cis_rule_1_1_2_3_1: false +rhel8cis_rule_1_1_2_3_2: false +rhel8cis_rule_1_1_2_3_3: false + +# /var +rhel8cis_rule_1_1_2_4_1: false +rhel8cis_rule_1_1_2_4_2: false +rhel8cis_rule_1_1_2_4_3: false + +# /var/tmp +rhel8cis_rule_1_1_2_5_1: false +rhel8cis_rule_1_1_2_5_2: false +rhel8cis_rule_1_1_2_5_3: false +rhel8cis_rule_1_1_2_5_4: false + +# /var/log +rhel8cis_rule_1_1_2_6_1: false +rhel8cis_rule_1_1_2_6_2: false +rhel8cis_rule_1_1_2_6_3: false +rhel8cis_rule_1_1_2_6_4: false + +# /var/log/audit +rhel8cis_rule_1_1_2_7_1: false +rhel8cis_rule_1_1_2_7_2: false +rhel8cis_rule_1_1_2_7_3: false +rhel8cis_rule_1_1_2_7_4: false + +# DNF - Patching +rhel8cis_rule_1_2_1: true rhel8cis_rule_1_2_2: true rhel8cis_rule_1_2_3: true rhel8cis_rule_1_2_4: true +rhel8cis_rule_1_2_5: true + +# bootloader grub rhel8cis_rule_1_3_1: false rhel8cis_rule_1_3_2: false + +# kernel sysctl and coredumps rhel8cis_rule_1_4_1: false rhel8cis_rule_1_4_2: false rhel8cis_rule_1_4_3: false -rhel8cis_rule_1_5_1: false -rhel8cis_rule_1_5_2: false -rhel8cis_rule_1_5_3: false +rhel8cis_rule_1_4_4: false + +# SElinux +rhel8cis_selinux_disable: true + +# Crypto Policies rhel8cis_rule_1_6_1: true -rhel8cis_rule_1_6_2: false -rhel8cis_rule_1_6_1_1: true -rhel8cis_rule_1_6_1_2: false -rhel8cis_rule_1_6_1_3: false -rhel8cis_rule_1_6_1_4: false -rhel8cis_rule_1_6_1_5: false -rhel8cis_rule_1_6_1_6: false -rhel8cis_rule_1_6_1_7: false -rhel8cis_rule_1_6_1_8: false +rhel8cis_rule_1_6_2: true +rhel8cis_rule_1_6_3: true +rhel8cis_rule_1_6_4: true + +# MOTD and messages rhel8cis_rule_1_7_1: true rhel8cis_rule_1_7_2: true rhel8cis_rule_1_7_3: true rhel8cis_rule_1_7_4: true rhel8cis_rule_1_7_5: true rhel8cis_rule_1_7_6: true -rhel8cis_rule_1_8_1: false -rhel8cis_rule_1_8_2: false -rhel8cis_rule_1_8_3: false -rhel8cis_rule_1_8_4: false -rhel8cis_rule_1_8_5: false -rhel8cis_rule_1_9: true + +# Gnome desktop +rhel8cis_gui: false # Section 2 rules rhel8cis_rule_2_1_1: true @@ -114,12 +134,18 @@ rhel8cis_rule_2_3_6: true rhel8cis_rule_2_4: true # Section 3 rules -rhel8cis_rule_3_1_1: true -rhel8cis_rule_3_1_2: true -rhel8cis_rule_3_1_3: true -rhel8cis_rule_3_1_4: true +# network connectivity wifi/bluetooth/ipv6 +rhel8cis_rule_3_1_1: false +rhel8cis_rule_3_1_2: false +rhel8cis_rule_3_1_3: false + +# Network Kernel module rhel8cis_rule_3_2_1: false rhel8cis_rule_3_2_2: false +rhel8cis_rule_3_2_3: false +rhel8cis_rule_3_2_4: false + +# Network Kernel Params rhel8cis_rule_3_3_1: false rhel8cis_rule_3_3_2: false rhel8cis_rule_3_3_3: false @@ -129,144 +155,172 @@ rhel8cis_rule_3_3_6: false rhel8cis_rule_3_3_7: false rhel8cis_rule_3_3_8: false rhel8cis_rule_3_3_9: false -rhel8cis_rule_3_4_1_1: true -rhel8cis_rule_3_4_1_2: true -rhel8cis_rule_3_4_1_3: true -rhel8cis_rule_3_4_1_4: true -rhel8cis_rule_3_4_1_5: true -rhel8cis_rule_3_4_1_6: true -rhel8cis_rule_3_4_1_7: true -rhel8cis_rule_3_4_2_1: true -rhel8cis_rule_3_4_2_2: true -rhel8cis_rule_3_4_2_3: true -rhel8cis_rule_3_4_2_4: true -rhel8cis_rule_3_4_2_5: true -rhel8cis_rule_3_4_2_6: true -rhel8cis_rule_3_4_2_7: true -rhel8cis_rule_3_4_2_8: true -rhel8cis_rule_3_4_2_9: true -rhel8cis_rule_3_4_2_10: true -rhel8cis_rule_3_4_2_11: true -rhel8cis_rule_3_4_3_1_1: true -rhel8cis_rule_3_4_3_1_2: true -rhel8cis_rule_3_4_3_1_3: true -rhel8cis_rule_3_4_3_2_1: true -rhel8cis_rule_3_4_3_2_2: true -rhel8cis_rule_3_4_3_2_3: true -rhel8cis_rule_3_4_3_2_4: true -rhel8cis_rule_3_4_3_2_5: true -rhel8cis_rule_3_4_3_2_6: true -rhel8cis_rule_3_4_3_3_1: true -rhel8cis_rule_3_4_3_3_2: true -rhel8cis_rule_3_4_3_3_3: true -rhel8cis_rule_3_4_3_3_4: true -rhel8cis_rule_3_4_3_3_5: true -rhel8cis_rule_3_4_3_3_6: true +rhel8cis_rule_3_3_10: false +rhel8cis_rule_3_3_11: false + +# Firewall +rhel8cis_firewall: none # Section 4 rules -rhel8cis_rule_4_1_1_1: false -rhel8cis_rule_4_1_1_2: false -rhel8cis_rule_4_1_1_3: false -rhel8cis_rule_4_1_1_4: false -rhel8cis_rule_4_1_2_1: false -rhel8cis_rule_4_1_2_2: false -rhel8cis_rule_4_1_2_3: false -rhel8cis_rule_4_1_3_1: false -rhel8cis_rule_4_1_3_2: false -rhel8cis_rule_4_1_3_3: false -rhel8cis_rule_4_1_3_4: false -rhel8cis_rule_4_1_3_5: false -rhel8cis_rule_4_1_3_6: false -rhel8cis_rule_4_1_3_7: false -rhel8cis_rule_4_1_3_8: false -rhel8cis_rule_4_1_3_9: false -rhel8cis_rule_4_1_3_10: false -rhel8cis_rule_4_1_3_11: false -rhel8cis_rule_4_1_3_12: false -rhel8cis_rule_4_1_3_13: false -rhel8cis_rule_4_1_3_14: false -rhel8cis_rule_4_1_3_15: false -rhel8cis_rule_4_1_3_16: false -rhel8cis_rule_4_1_3_17: false -rhel8cis_rule_4_1_3_18: false -rhel8cis_rule_4_1_3_19: false -rhel8cis_rule_4_1_3_20: false -rhel8cis_rule_4_1_3_21: false -rhel8cis_rule_4_2_1_1: true -rhel8cis_rule_4_2_1_2: true -rhel8cis_rule_4_2_1_3: true -rhel8cis_rule_4_2_1_4: true -rhel8cis_rule_4_2_1_5: true -rhel8cis_rule_4_2_1_6: true -rhel8cis_rule_4_2_1_7: true -rhel8cis_rule_4_2_2_1_1: true -rhel8cis_rule_4_2_2_1_2: true -rhel8cis_rule_4_2_2_1_3: true -rhel8cis_rule_4_2_2_1_4: true -rhel8cis_rule_4_2_2_2: true -rhel8cis_rule_4_2_2_3: true -rhel8cis_rule_4_2_2_4: true -rhel8cis_rule_4_2_2_5: true -rhel8cis_rule_4_2_2_6: true -rhel8cis_rule_4_2_2_7: true -rhel8cis_rule_4_2_3: false -rhel8cis_rule_4_3: true +# cron +rhel8cis_rule_4_1_1_1: true +rhel8cis_rule_4_1_1_2: true +rhel8cis_rule_4_1_1_3: true +rhel8cis_rule_4_1_1_4: true +rhel8cis_rule_4_1_1_5: true +rhel8cis_rule_4_1_1_6: true +rhel8cis_rule_4_1_1_7: true +rhel8cis_rule_4_1_1_8: true + +# at +rhel8cis_rule_4_1_2_1: true + +# sshd +# Only if installed + +# sudo +rhel8cis_rule_4_3_1: false +rhel8cis_rule_4_3_2: false +rhel8cis_rule_4_3_3: false +rhel8cis_rule_4_3_4: false +rhel8cis_rule_4_3_5: false +rhel8cis_rule_4_3_6: false +rhel8cis_rule_4_3_7: false + +# Pam software pkgs +rhel8cis_rule_4_4_1_1: false +rhel8cis_rule_4_4_1_2: false + +# authselect +rhel8cis_rule_4_4_2_1: false +rhel8cis_rule_4_4_2_2: false +rhel8cis_rule_4_4_2_3: false +rhel8cis_rule_4_4_2_4: false +rhel8cis_rule_4_4_2_5: false + +# pam faillock +rhel8cis_rule_4_4_3_1_1: false +rhel8cis_rule_4_4_3_1_2: false +rhel8cis_rule_4_4_3_1_3: false + +# pam pwquality +rhel8cis_rule_4_4_3_2_1: false +rhel8cis_rule_4_4_3_2_2: false +rhel8cis_rule_4_4_3_2_3: false +rhel8cis_rule_4_4_3_2_4: false +rhel8cis_rule_4_4_3_2_5: false +rhel8cis_rule_4_4_3_2_6: false +rhel8cis_rule_4_4_3_2_7: false + +# pam pwhistory +rhel8cis_rule_4_4_3_3_1: false +rhel8cis_rule_4_4_3_3_2: false +rhel8cis_rule_4_4_3_3_3: false + +# pam pam_unix +rhel8cis_rule_4_4_3_4_1: false +rhel8cis_rule_4_4_3_4_2: false +rhel8cis_rule_4_4_3_4_3: false +rhel8cis_rule_4_4_3_4_4: false + +# Shadow user settings +rhel8cis_rule_4_5_1_1: true +rhel8cis_rule_4_5_1_2: true +rhel8cis_rule_4_5_1_3: true +rhel8cis_rule_4_5_1_4: true +rhel8cis_rule_4_5_1_5: true + +# root and sys accts and env +rhel8cis_rule_4_5_2_1: true +rhel8cis_rule_4_5_2_2: true +rhel8cis_rule_4_5_2_3: true +rhel8cis_rule_4_5_2_4: true +rhel8cis_rule_4_5_2_5: true + +# User enviroment +rhel8cis_rule_4_5_3_1: true +rhel8cis_rule_4_5_3_2: true +rhel8cis_rule_4_5_3_3: true # Section 5 rules -rhel8cis_rule_5_1_1: false -rhel8cis_rule_5_1_2: false -rhel8cis_rule_5_1_3: false -rhel8cis_rule_5_1_4: false -rhel8cis_rule_5_1_5: false -rhel8cis_rule_5_1_6: false -rhel8cis_rule_5_1_7: false -rhel8cis_rule_5_1_8: false -rhel8cis_rule_5_1_9: false -rhel8cis_rule_5_2_1: false -rhel8cis_rule_5_2_2: true -rhel8cis_rule_5_2_3: true -rhel8cis_rule_5_2_4: true -rhel8cis_rule_5_2_5: true -rhel8cis_rule_5_2_6: true -rhel8cis_rule_5_2_7: true -rhel8cis_rule_5_2_8: true -rhel8cis_rule_5_2_9: true -rhel8cis_rule_5_2_10: true -rhel8cis_rule_5_2_12: true -rhel8cis_rule_5_2_11: true -rhel8cis_rule_5_2_13: true -rhel8cis_rule_5_2_14: true -rhel8cis_rule_5_2_15: true -rhel8cis_rule_5_2_16: true -rhel8cis_rule_5_2_17: true -rhel8cis_rule_5_2_18: true -rhel8cis_rule_5_2_19: true -rhel8cis_rule_5_2_20: true + +rhel8cis_syslog: none + +# Rsyslog +rhel8cis_rule_5_1_1_1: true +rhel8cis_rule_5_1_1_2: true +rhel8cis_rule_5_1_1_3: true +rhel8cis_rule_5_1_1_4: true +rhel8cis_rule_5_1_1_5: true +rhel8cis_rule_5_1_1_6: true +rhel8cis_rule_5_1_1_7: true + +# Journald +rhel8cis_rule_5_1_2_1_1: true +rhel8cis_rule_5_1_2_1_2: true +rhel8cis_rule_5_1_2_1_3: true +rhel8cis_rule_5_1_2_1_4: true +rhel8cis_rule_5_1_2_2: true +rhel8cis_rule_5_1_2_3: true +rhel8cis_rule_5_1_2_4: true +rhel8cis_rule_5_1_2_5: true +rhel8cis_rule_5_1_2_6: true +rhel8cis_rule_5_1_3: true +rhel8cis_rule_5_1_4: true + +# Auditd +rhel8cis_rule_5_2_1_1: true +rhel8cis_rule_5_2_1_2: true +rhel8cis_rule_5_2_1_3: true +rhel8cis_rule_5_2_1_4: true +rhel8cis_rule_5_2_2_1: true +rhel8cis_rule_5_2_2_2: true +rhel8cis_rule_5_2_2_3: true +rhel8cis_rule_5_2_2_4: true + +# auditd rules +rhel8cis_rule_5_2_3_1: true +rhel8cis_rule_5_2_3_2: true +rhel8cis_rule_5_2_3_3: true +rhel8cis_rule_5_2_3_4: true +rhel8cis_rule_5_2_3_5: true +rhel8cis_rule_5_2_3_6: true +rhel8cis_rule_5_2_3_7: true +rhel8cis_rule_5_2_3_8: true +rhel8cis_rule_5_2_3_9: true +rhel8cis_rule_5_2_3_10: true +rhel8cis_rule_5_2_3_11: true +rhel8cis_rule_5_2_3_12: true +rhel8cis_rule_5_2_3_13: true +rhel8cis_rule_5_2_3_14: true +rhel8cis_rule_5_2_3_15: true +rhel8cis_rule_5_2_3_16: true +rhel8cis_rule_5_2_3_17: true +rhel8cis_rule_5_2_3_18: true +rhel8cis_rule_5_2_3_19: true +rhel8cis_rule_5_2_3_20: true +rhel8cis_rule_5_2_3_21: true + +# auditd log perms +rhel8cis_rule_5_2_4_1: true +rhel8cis_rule_5_2_4_2: true +rhel8cis_rule_5_2_4_3: true +rhel8cis_rule_5_2_4_4: true +rhel8cis_rule_5_2_4_5: true +rhel8cis_rule_5_2_4_6: true +rhel8cis_rule_5_2_4_7: true +rhel8cis_rule_5_2_4_8: true +rhel8cis_rule_5_2_4_9: true +rhel8cis_rule_5_2_4_10: true + +# AIDE + rhel8cis_rule_5_3_1: true rhel8cis_rule_5_3_2: true rhel8cis_rule_5_3_3: true -rhel8cis_rule_5_3_4: false -rhel8cis_rule_5_3_5: false -rhel8cis_rule_5_3_6: true -rhel8cis_rule_5_3_7: true -rhel8cis_rule_5_4_1: false -rhel8cis_rule_5_4_2: false -rhel8cis_rule_5_5_1: true -rhel8cis_rule_5_5_2: true -rhel8cis_rule_5_5_3: true -rhel8cis_rule_5_5_4: false -rhel8cis_rule_5_5_5: true -rhel8cis_rule_5_6_1_1: true -rhel8cis_rule_5_6_1_2: true -rhel8cis_rule_5_6_1_3: true -rhel8cis_rule_5_6_1_4: true -rhel8cis_rule_5_6_1_5: true -rhel8cis_rule_5_6_2: true -rhel8cis_rule_5_6_3: true -rhel8cis_rule_5_6_4: true -rhel8cis_rule_5_6_5: true # Section 6 rules +# System file perms rhel8cis_rule_6_1_1: true rhel8cis_rule_6_1_2: true rhel8cis_rule_6_1_3: true @@ -281,7 +335,8 @@ rhel8cis_rule_6_1_11: true rhel8cis_rule_6_1_12: true rhel8cis_rule_6_1_13: true rhel8cis_rule_6_1_14: true -rhel8cis_rule_6_1_15: true + +# local and usergroup rhel8cis_rule_6_2_1: true rhel8cis_rule_6_2_2: true rhel8cis_rule_6_2_3: true @@ -289,12 +344,7 @@ rhel8cis_rule_6_2_4: true rhel8cis_rule_6_2_5: true rhel8cis_rule_6_2_6: true rhel8cis_rule_6_2_7: true -rhel8cis_rule_6_2_8: false +rhel8cis_rule_6_2_8: true rhel8cis_rule_6_2_9: true -rhel8cis_rule_6_2_10: true +rhel8cis_rule_6_2_10: false rhel8cis_rule_6_2_11: true -rhel8cis_rule_6_2_12: true -rhel8cis_rule_6_2_13: true -rhel8cis_rule_6_2_14: true -rhel8cis_rule_6_2_15: true -rhel8cis_rule_6_2_16: true From 197aa4a48aef836f2b449acf6a522a15484347c5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:02:31 +0100 Subject: [PATCH 12/62] [pre-commit.ci] pre-commit autoupdate (#367) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v4.5.0 → v4.6.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.5.0...v4.6.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 45d1df9c..177c0e9c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ ci: repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: # Safety - id: detect-aws-credentials From 1de4490e5497c260b1fc96d67e9aa8a012e563c9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:37:49 +0100 Subject: [PATCH 13/62] [pre-commit.ci] pre-commit autoupdate (#368) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v24.2.1 → v24.2.2](https://github.com/ansible-community/ansible-lint/compare/v24.2.1...v24.2.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 177c0e9c..485d4ae4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -44,7 +44,7 @@ repos: exclude: .config/.secrets.baseline - repo: https://github.com/ansible-community/ansible-lint - rev: v24.2.1 + rev: v24.2.2 hooks: - id: ansible-lint name: Ansible-lint From 7509256bf2ced8db3edf5f9b353a8b183068c527 Mon Sep 17 00:00:00 2001 From: uk-bolly Date: Thu, 25 Apr 2024 14:42:53 +0100 Subject: [PATCH 14/62] updated for audit and url alignment (#370) Signed-off-by: Mark Bolwell --- defaults/main.yml | 43 ++++++++++++++++++++++++-------- tasks/LE_audit_setup.yml | 4 +-- tasks/audit_only.yml | 2 +- tasks/post_remediation_audit.yml | 6 ++--- tasks/pre_remediation_audit.yml | 22 ++++++++-------- vars/audit.yml | 32 +++++++----------------- 6 files changed, 60 insertions(+), 49 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 0c419114..074f1258 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -37,37 +37,60 @@ benchmark_version: v3.0.0 # Whether to skip the reboot skip_reboot: true -########################################## +### +### Settings for associated Audit role using Goss +### + +########################################### ### Goss is required on the remote host ### -## Refer to vars/auditd.yml for any other settings ## +### vars/auditd.yml for other settings ### # Allow audit to setup the requirements including installing git (if option chosen and downloading and adding goss binary to system) setup_audit: false # enable audits to run - this runs the audit and get the latest content run_audit: false +# Run heavy tests - some tests can have more impact on a system enabling these can have greater impact on a system +audit_run_heavy_tests: true -# Only run Audit do not remediate +## Only run Audit do not remediate audit_only: false -# As part of audit_only -# This will enable files to be copied back to control node +### As part of audit_only ### +# This will enable files to be copied back to control node in audit_only mode fetch_audit_files: false -# Path to copy the files to will create dir structure +# Path to copy the files to will create dir structure in audit_only mode audit_capture_files_dir: /some/location to copy to on control node +############################# # How to retrieve audit binary # Options are copy or download - detailed settings at the bottom of this file # you will need to access to either github or the file already dowmloaded get_audit_binary_method: download +## if get_audit_binary_method - copy the following needs to be updated for your environment +## it is expected that it will be copied from somewhere accessible to the control node +## e.g copy from ansible control node to remote host +audit_bin_copy_location: /some/accessible/path + # how to get audit files onto host options -# options are git/copy/get_url other e.g. if you wish to run from already downloaded conf +# options are git/copy/archive/get_url other e.g. if you wish to run from already downloaded conf audit_content: git -# Run heavy tests - some tests can have more impact on a system enabling these can have greater impact on a system -audit_run_heavy_tests: true +# If using either archive, copy, get_url: +## Note will work with .tar files - zip will require extra configuration +### If using get_url this is expecting github url in tar.gz format e.g. +### https://github.com/ansible-lockdown/UBUNTU22-CIS-Audit/archive/refs/heads/benchmark-v1.0.0.tar.gz +audit_conf_source: "some path or url to copy from" + +# Destination for the audit content to be placed on managed node +# note may not need full path e.g. /opt with the directory being the {{ benchmark }}-Audit directory +audit_conf_dest: "/opt" + +# Where the audit logs are stored +audit_log_dir: '/opt' -### End Goss enablements #### +### Goss Settings ## +####### END ######## # These variables correspond with the CIS rule IDs or paragraph numbers defined in # the CIS benchmark documents. diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index b7c0b9ba..70674142 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -3,12 +3,12 @@ - name: Pre Audit Setup | Set audit package name block: - name: Pre Audit Setup | Set audit package name | 64bit - when: ansible_machine == "x86_64" + when: ansible_facts.machine == "x86_64" ansible.builtin.set_fact: audit_pkg_arch_name: AMD64 - name: Pre Audit Setup | Set audit package name | ARM64 - when: ansible_machine == "arm64" + when: ansible_facts.machine == "arm64" ansible.builtin.set_fact: audit_pkg_arch_name: ARM64 diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index f267a1e7..d34b90f0 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -22,7 +22,7 @@ when: - audit_only ansible.builtin.debug: - msg: "The Audit results are: {{ pre_audit_summary }}." + msg: "{{ audit_results.split('\n') }}" - name: Audit_only | Stop Playbook Audit Only selected when: diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 78c84e63..19dff268 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -5,7 +5,7 @@ changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" - AUDIT_CONTENT_LOCATION: "{{ audit_out_dir }}" + AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" AUDIT_FILE: goss.yml - name: Post Audit | Ensure audit files readable by users @@ -22,7 +22,7 @@ - audit_format == "json" block: - name: Post Audit | Capture data {{ post_audit_outfile }} - ansible.builtin.shell: cat {{ post_audit_outfile }} + ansible.builtin.shell: "cat {{ post_audit_outfile }}" register: discovered_post_audit changed_when: false @@ -37,7 +37,7 @@ - audit_format == "documentation" block: - name: Post Audit | Capture data {{ post_audit_outfile }} - ansible.builtin.shell: tail -2 {{ post_audit_outfile }} + ansible.builtin.shell: "tail -2 {{ post_audit_outfile }}" register: discovered_post_audit changed_when: false diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 75e4d154..fb6d709f 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -33,23 +33,25 @@ when: - audit_content == 'copy' ansible.builtin.copy: - src: "{{ audit_local_copy }}" + src: "{{ audit_conf_source }}" dest: "{{ audit_conf_dest }}" mode: preserve - name: Pre Audit Setup | Unarchive audit content files on server when: - - audit_content == 'archived' + - audit_content == 'archive' ansible.builtin.unarchive: - src: "{{ audit_conf_copy }}" - dest: "{{ audit_conf_dir }}" + src: "{{ audit_conf_source }}" + dest: "{{ audit_conf_dest }}" - name: Pre Audit Setup | Get audit content from url when: - audit_content == 'get_url' - ansible.builtin.get_url: - url: "{{ audit_files_url }}" - dest: "{{ audit_conf_dir }}" + ansible.builtin.unarchive: + src: "{{ audit_conf_source }}" + dest: "{{ audit_conf_dest }}/{{ benchmark }}-Audit" + remote_src: "{{ ( audit_conf_source is contains ('http'))| ternary(true, false ) }}" + extra_opts: "{{ (audit_conf_source is contains ('github')) | ternary('--strip-components=1', [] ) }}" - name: Pre Audit Setup | Check Goss is available when: @@ -81,7 +83,7 @@ changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" - AUDIT_CONTENT_LOCATION: "{{ audit_out_dir }}" + AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" AUDIT_FILE: goss.yml - name: Pre Audit | Capture audit data if json format @@ -89,7 +91,7 @@ - audit_format == "json" block: - name: Pre Audit | Capture data {{ pre_audit_outfile }} - ansible.builtin.shell: cat {{ pre_audit_outfile }} + ansible.builtin.shell: "cat {{ pre_audit_outfile }}" register: discovered_pre_audit changed_when: false @@ -104,7 +106,7 @@ - audit_format == "documentation" block: - name: Pre Audit | Capture data {{ pre_audit_outfile }} | documentation format - ansible.builtin.shell: tail -2 {{ pre_audit_outfile }} + ansible.builtin.shell: "tail -2 {{ pre_audit_outfile }}" register: discovered_pre_audit changed_when: false diff --git a/vars/audit.yml b/vars/audit.yml index 250a600e..bb50f6d3 100644 --- a/vars/audit.yml +++ b/vars/audit.yml @@ -2,40 +2,25 @@ #### Audit Configuration Settings #### -# This variable specifies the timeout (in ms) for audit commands that -# take a very long time: if a command takes too long to complete, -# it will be forcefully terminated after the specified duration. +# Timeout for those cmds that take longer to run where timeout set audit_cmd_timeout: 120000 # if get_audit_binary_method == download change accordingly audit_bin_url: "https://github.com/goss-org/goss/releases/download/{{ audit_bin_version.release }}/goss-linux-" -## if get_audit_binary_method - copy the following needs to be updated for your environment -## it is expected that it will be copied from somewhere accessible to the control node -## e.g copy from ansible control node to remote host -audit_bin_copy_location: /some/accessible/path - ### Goss Audit Benchmark file ### ## managed by the control audit_content # git audit_file_git: "https://github.com/ansible-lockdown/{{ benchmark }}-Audit.git" audit_git_version: "benchmark_{{ benchmark_version }}" -# archive or copy: -audit_conf_copy: "some path to copy from" - -# get_url: -audit_files_url: "some url maybe s3?" - ## Goss configuration information -# Where the goss configs and outputs are stored -audit_out_dir: '/opt' -# Where the goss audit configuration will be stored -audit_conf_dir: "{{ audit_out_dir }}/{{ benchmark }}-Audit" +# Where the goss audit configuration will be stored - NOTE benchmark-audit is expected +audit_conf_dir: "{{ audit_conf_dest | default('/opt') }}/{{ benchmark }}-Audit" # If changed these can affect other products -pre_audit_outfile: "{{ audit_out_dir }}/{{ ansible_facts.hostname }}-{{ benchmark }}-{{ benchmark_version }}_pre_scan_{{ ansible_facts.date_time.epoch }}.{{ audit_format }}" -post_audit_outfile: "{{ audit_out_dir }}/{{ ansible_facts.hostname }}-{{ benchmark }}-{{ benchmark_version }}_post_scan_{{ ansible_facts.date_time.epoch }}.{{ audit_format }}" +pre_audit_outfile: "{{ audit_log_dir }}/{{ ansible_facts.hostname }}-{{ benchmark }}-{{ benchmark_version }}_pre_scan_{{ ansible_facts.date_time.epoch }}.{{ audit_format }}" +post_audit_outfile: "{{ audit_log_dir }}/{{ ansible_facts.hostname }}-{{ benchmark }}-{{ benchmark_version }}_post_scan_{{ ansible_facts.date_time.epoch }}.{{ audit_format }}" ## The following should not need changing @@ -49,6 +34,7 @@ audit_format: json audit_vars_path: "{{ audit_conf_dir }}/vars/{{ ansible_facts.hostname }}.yml" audit_results: | - The pre remediation results are: {{ pre_audit_summary }}. - The post remediation results are: {{ post_audit_summary }}. - Full breakdown can be found in {{ audit_out_dir }} + The audit results are: {{ pre_audit_summary }} + {% if not audit_only %}The post remediation audit results are: {{ post_audit_summary }}{% endif %} + + Full breakdown can be found in {{ audit_log_dir }} From 3c0ac3ebad5aaa76d3cc27d366cc0eed67ca9368 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 12 Jun 2024 14:06:11 +0100 Subject: [PATCH 15/62] [pre-commit.ci] pre-commit autoupdate (#372) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/Yelp/detect-secrets: v1.4.0 → v1.5.0](https://github.com/Yelp/detect-secrets/compare/v1.4.0...v1.5.0) - [github.com/gitleaks/gitleaks: v8.18.2 → v8.18.3](https://github.com/gitleaks/gitleaks/compare/v8.18.2...v8.18.3) - [github.com/ansible-community/ansible-lint: v24.2.2 → v24.6.0](https://github.com/ansible-community/ansible-lint/compare/v24.2.2...v24.6.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 485d4ae4..ce7987c0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,21 +30,21 @@ repos: # Scan for passwords - repo: https://github.com/Yelp/detect-secrets - rev: v1.4.0 + rev: v1.5.0 hooks: - id: detect-secrets args: ['--baseline', '.config/.secrets.baseline'] exclude: package.lock.json - repo: https://github.com/gitleaks/gitleaks - rev: v8.18.2 + rev: v8.18.3 hooks: - id: gitleaks args: ['--baseline-path', '.config/.gitleaks-report.json'] exclude: .config/.secrets.baseline - repo: https://github.com/ansible-community/ansible-lint - rev: v24.2.2 + rev: v24.6.0 hooks: - id: ansible-lint name: Ansible-lint From cd73c356cf2f2e3babe7beba40d09514b2395873 Mon Sep 17 00:00:00 2001 From: tomkuba Date: Wed, 12 Jun 2024 15:15:19 +0200 Subject: [PATCH 16/62] use RHEL8 chrony.conf (#371) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomáš Kuba --- templates/chrony.conf.j2 | 107 ++++++++++----------------------------- 1 file changed, 27 insertions(+), 80 deletions(-) diff --git a/templates/chrony.conf.j2 b/templates/chrony.conf.j2 index e0c31130..12581798 100644 --- a/templates/chrony.conf.j2 +++ b/templates/chrony.conf.j2 @@ -1,95 +1,42 @@ -## This file is managed by Ansible, YOUR CHANGED WILL BE LOST! - -# This the default chrony.conf file for the Debian chrony package. After -# editing this file use the command 'invoke-rc.d chrony restart' to make -# your changes take effect. John Hasler 1998-2008 - -# See www.pool.ntp.org for an explanation of these servers. Please -# consider joining the project if possible. If you can't or don't want to -# use these servers I suggest that you try your ISP's nameservers. We mark -# the servers 'offline' so that chronyd won't try to connect when the link -# is down. Scripts in /etc/ppp/ip-up.d and /etc/ppp/ip-down.d use chronyc -# commands to switch it on when a dialup link comes up and off when it goes -# down. Code in /etc/init.d/chrony attempts to determine whether or not -# the link is up at boot time and set the online status accordingly. If -# you have an always-on connection such as cable omit the 'offline' -# directive and chronyd will default to online. -# -# Note that if Chrony tries to go "online" and dns lookup of the servers -# fails they will be discarded. Thus under some circumstances it is -# better to use IP numbers than host names. +{{ ansible_managed | comment }} +# Use public servers from the pool.ntp.org project. +# Please consider joining the pool (http://www.pool.ntp.org/join.html). {% for server in rhel8cis_time_synchronization_servers -%} server {{ server }} {{ rhel8cis_chrony_server_options }} {% endfor %} -# Look here for the admin password needed for chronyc. The initial -# password is generated by a random process at install time. You may -# change it if you wish. - -keyfile /etc/chrony/chrony.keys - -# Set runtime command key. Note that if you change the key (not the -# password) to anything other than 1 you will need to edit -# /etc/ppp/ip-up.d/chrony, /etc/ppp/ip-down.d/chrony, /etc/init.d/chrony -# and /etc/cron.weekly/chrony as these scripts use it to get the password. - -commandkey 1 - -# I moved the driftfile to /var/lib/chrony to comply with the Debian -# filesystem standard. - -driftfile /var/lib/chrony/chrony.drift - -# Comment this line out to turn off logging. - -log tracking measurements statistics -logdir /var/log/chrony - -# Stop bad estimates upsetting machine clock. - -maxupdateskew 100.0 - -# Dump measurements when daemon exits. - -dumponexit +# Record the rate at which the system clock gains/losses time. +driftfile /var/lib/chrony/drift -# Specify directory for dumping measurements. +# Allow the system clock to be stepped in the first three updates +# if its offset is larger than 1 second. +makestep 1.0 3 -dumpdir /var/lib/chrony +# Enable kernel synchronization of the real-time clock (RTC). +rtcsync -# Let computer be a server when it is unsynchronised. +# Enable hardware timestamping on all interfaces that support it. +#hwtimestamp * -local stratum 10 +# Increase the minimum number of selectable sources required to adjust +# the system clock. +#minsources 2 -# Allow computers on the unrouted nets to use the server. +# Allow NTP client access from local network. +#allow 192.168.0.0/16 -#allow 10/8 -#allow 192.168/16 -#allow 172.16/12 +# Serve time even if not synchronized to a time source. +#local stratum 10 -# This directive forces `chronyd' to send a message to syslog if it -# makes a system clock adjustment larger than a threshold value in seconds. +# Specify file containing keys for NTP authentication. +keyfile /etc/chrony.keys -logchange 0.5 +# Get TAI-UTC offset and leap seconds from the system tz database. +leapsectz right/UTC -# This directive defines an email address to which mail should be sent -# if chronyd applies a correction exceeding a particular threshold to the -# system clock. - -# mailonchange root@localhost 0.5 - -# This directive tells chrony to regulate the real-time clock and tells it -# Where to store related data. It may not work on some newer motherboards -# that use the HPET real-time clock. It requires enhanced real-time -# support in the kernel. I've commented it out because with certain -# combinations of motherboard and kernel it is reported to cause lockups. - -# rtcfile /var/lib/chrony/chrony.rtc +# Specify directory for log files. +logdir /var/log/chrony -# If the last line of this file reads 'rtconutc' chrony will assume that -# the CMOS clock is on UTC (GMT). If it reads '# rtconutc' or is absent -# chrony will assume local time. The line (if any) was written by the -# chrony postinst based on what it found in /etc/default/rcS. You may -# change it if necessary. -rtconutc +# Select which information is logged. +#log measurements statistics tracking From 0f4f7b35a3ac79d9545849df931f48b7b980449b Mon Sep 17 00:00:00 2001 From: ajython Date: Fri, 14 Jun 2024 16:37:36 +0100 Subject: [PATCH 17/62] Update Alma 8 GPG Key (#369) * Update Alma 8 GPG Key Update AlmaLinux.yml Signed-off-by: ajython * Update AlmaLinux.yml Replace depricated Alma 8 GPG key Signed-off-by: ajython --------- Signed-off-by: ajython --- vars/AlmaLinux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vars/AlmaLinux.yml b/vars/AlmaLinux.yml index 7c7ea872..7e7ca9be 100644 --- a/vars/AlmaLinux.yml +++ b/vars/AlmaLinux.yml @@ -4,4 +4,4 @@ rpm_gpg_key: /etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux rpm_packager: "AlmaLinux Packaging Team" # found on https://wiki.almalinux.org/cloud/Generic-cloud.html#download-and-verification note lower cas -rpm_key: "51d6647ec21ad6ea" # pragma: allowlist secret +rpm_key: "2ae81e8aced7258b" # pragma: allowlist secret https://almalinux.org/blog/2023-12-20-almalinux-8-key-update/ From 436f3e4b92f4bfad85fe1889124a3e735d496e36 Mon Sep 17 00:00:00 2001 From: uk-bolly Date: Mon, 17 Jun 2024 07:29:27 +0100 Subject: [PATCH 18/62] May 24 updates (#376) * updated path to match disa for audit tools Signed-off-by: Mark Bolwell * updated dict control Signed-off-by: Mark Bolwell * updated nullok logic Signed-off-by: Mark Bolwell * updated typos Signed-off-by: Mark Bolwell * updated typ thanks to @msachikanta Signed-off-by: Mark Bolwell --------- Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 2 +- tasks/section_4/cis_4.3.x.yml | 14 +++----------- tasks/section_4/cis_4.4.3.2.x.yml | 3 ++- tasks/section_4/cis_4.4.3.4.x.yml | 9 +++++---- tasks/section_5/cis_5.3.x.yml | 12 ++++++------ templates/etc/systemd/system/tmp.mount.j2 | 2 +- 6 files changed, 18 insertions(+), 24 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 1eade936..4976158a 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -180,7 +180,7 @@ changed_when: false failed_when: false check_mode: false - register: discovered_sudoers_filess + register: discovered_sudoers_files - name: "PRELIM | AUDIT | Check authselect package versions" tags: diff --git a/tasks/section_4/cis_4.3.x.yml b/tasks/section_4/cis_4.3.x.yml index cfc15781..4ad33145 100644 --- a/tasks/section_4/cis_4.3.x.yml +++ b/tasks/section_4/cis_4.3.x.yml @@ -64,7 +64,7 @@ regexp: '^([^#|{% if system_is_ec2 %}ec2-user{% endif %}].*)NOPASSWD(.*)' replace: '\1PASSWD\2' validate: '/usr/sbin/visudo -cf %s' - loop: "{{ discovered_sudoers_filess.stdout_lines }}" + loop: "{{ discovered_sudoers_files.stdout_lines }}" - name: "4.3.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally" when: @@ -82,7 +82,7 @@ regexp: '^([^#].*)!authenticate(.*)' replace: '\1authenticate\2' validate: '/usr/sbin/visudo -cf %s' - loop: "{{ discovered_sudoers_filess.stdout_lines }}" + loop: "{{ discovered_sudoers_files.stdout_lines }}" - name: "4.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly" when: @@ -135,17 +135,9 @@ ansible.builtin.group: name: "{{ rhel8cis_sugroup }}" state: present - register: discovered_sugroup - - - name: "4.3.7 | PATCH | Ensure access to the su command is restricted | remove users from group" - ansible.builtin.lineinfile: - path: /etc/group - regexp: '^{{ discovered_sugroup }}(:.:.*:).*$' - line: '{{ discovered_sugroup }}\g<1>' - backrefs: true - name: "4.3.7 | PATCH | Ensure access to the su command is restricted | Setting pam_wheel to use_uid" ansible.builtin.lineinfile: path: /etc/pam.d/su regexp: '^(#)?auth\s+required\s+pam_wheel\.so' - line: 'auth required pam_wheel.so use_uid group={{ discovered_sugroup }}' + line: 'auth required pam_wheel.so use_uid group={{ rhel8cis_sugroup }}' diff --git a/tasks/section_4/cis_4.4.3.2.x.yml b/tasks/section_4/cis_4.4.3.2.x.yml index 356b5935..c3f8e1fd 100644 --- a/tasks/section_4/cis_4.4.3.2.x.yml +++ b/tasks/section_4/cis_4.4.3.2.x.yml @@ -224,9 +224,10 @@ block: - name: "4.4.3.2.6 | PATCH | Ensure password dictionary check is enabled | pwquality.conf" ansible.builtin.lineinfile: + line: 'dictcheck = 1' path: /etc/security/pwquality.conf - state: absent regexp: '^(#|)\s*dictcheck\s*=\s*\d' + state: present - name: "4.4.3.2.6 | PATCH | Ensure password dictionary check is enabled | pam_files" when: not rhel8cis_allow_authselect_updates diff --git a/tasks/section_4/cis_4.4.3.4.x.yml b/tasks/section_4/cis_4.4.3.4.x.yml index d8f5489e..65ba5768 100644 --- a/tasks/section_4/cis_4.4.3.4.x.yml +++ b/tasks/section_4/cis_4.4.3.4.x.yml @@ -23,8 +23,9 @@ - not rhel8cis_allow_authselect_updates ansible.builtin.replace: path: "/etc/pam.d/{{ item }}-auth" - regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)nullok(.*$) - replace: \1\2\3 + #regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)nullok(.*$) + regexp: nullok + replace: '' loop: - password - system @@ -107,8 +108,8 @@ - discovered_hash_state | length > 0 ansible.builtin.replace: path: "/etc/pam.d/{{ item }}-auth" - regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)(sha512|yescrypt)\s*=\s*\d+(.*$) - replace: \1\2\4 {{ discovered_hash_state.stdout }} + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)(sha512|yescrypt)(.*$) + replace: \1\2\4 {{ rhel8cis_pam_pwhash }} loop: - password - system diff --git a/tasks/section_5/cis_5.3.x.yml b/tasks/section_5/cis_5.3.x.yml index 754f57b4..bb955a9e 100644 --- a/tasks/section_5/cis_5.3.x.yml +++ b/tasks/section_5/cis_5.3.x.yml @@ -85,10 +85,10 @@ path: /etc/aide.conf marker: "# {mark} Audit tools - CIS benchmark - Ansible-lockdown" block: | - /sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512 - /sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512 - /sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512 - /sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512 - /sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512 - /sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512 + /usr/sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512 + /usr/sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512 + /usr/sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512 + /usr/sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512 + /usr/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512 + /usr/sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512 validate: aide -D --config %s diff --git a/templates/etc/systemd/system/tmp.mount.j2 b/templates/etc/systemd/system/tmp.mount.j2 index 2e3a1896..3cf0bf8b 100644 --- a/templates/etc/systemd/system/tmp.mount.j2 +++ b/templates/etc/systemd/system/tmp.mount.j2 @@ -23,7 +23,7 @@ After=swap.target What=tmpfs Where=/tmp Type=tmpfs -Options=mode=1777,strictatime,{% if rhel8cis_rule_1_1_2_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_4 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_2_3 %}noexec{% endif %} +Options=mode=1777,strictatime,{% if rhel8cis_rule_1_1_2_1_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_1_3 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_2_1_4 %}noexec{% endif %} # Make 'systemctl enable tmp.mount' work: [Install] From 069fc404b9c059c603b7a9a9e825d8ef59105c27 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 19:32:11 +0100 Subject: [PATCH 19/62] [pre-commit.ci] pre-commit autoupdate (#383) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.18.3 → v8.18.4](https://github.com/gitleaks/gitleaks/compare/v8.18.3...v8.18.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ce7987c0..1e9eee39 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,7 +37,7 @@ repos: exclude: package.lock.json - repo: https://github.com/gitleaks/gitleaks - rev: v8.18.3 + rev: v8.18.4 hooks: - id: gitleaks args: ['--baseline-path', '.config/.gitleaks-report.json'] From 08f6e77080ff4f958043ee92689133ad09ecbfaa Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 18 Jun 2024 20:49:28 +0100 Subject: [PATCH 20/62] updated known issues thanks to @fgierlinger Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 4 ++-- tasks/section_2/cis_2.1.x.yml | 5 +++-- tasks/section_4/cis_4.2.x.yml | 10 +++++----- tasks/section_4/cis_4.4.3.4.x.yml | 1 - 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 4976158a..f00e4e6d 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -385,10 +385,10 @@ - name: "PRELIM | Optional | If IPv6 disable to stop chronyd listening" when: discovered_chrony_ipv6_exists.stdout | length == 0 ansible.builtin.lineinfile: - backrefs: true path: /etc/sysconfig/chronyd - regexp: ^OPTIONS="(.*)" + regexp: '^OPTIONS="(?!.* -4.*)(.*)"' line: OPTIONS="\1 -4" + backrefs: true # Optional extra keys to extend auditd not part of CIS but can influence a system # e.g. admin_space_left: '10%' diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index 0de15e28..9738e6bf 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -45,8 +45,9 @@ - rule_2.1.3 ansible.builtin.lineinfile: path: /etc/sysconfig/chronyd - regexp: OPTIONS=\"(.*)(?!-u chrony)(.*)" - line: OPTIONS="\1\2 -u chrony" + regexp: '^OPTIONS="(?!.* -u chrony.*)(.*)"' + line: OPTIONS="\1 -u chrony" create: true backrefs: true mode: '0644' + notify: Restart_chronyd diff --git a/tasks/section_4/cis_4.2.x.yml b/tasks/section_4/cis_4.2.x.yml index 37a9cdda..e0c240ed 100644 --- a/tasks/section_4/cis_4.2.x.yml +++ b/tasks/section_4/cis_4.2.x.yml @@ -206,16 +206,16 @@ - rule_4.2.8 block: - name: "4.2.8 | PATCH | Ensure sshd DisableForwarding is enabled" - ansible.builtin.lineinfile: + ansible.builtin.replace: path: /etc/ssh/sshd_config - regexp: "^#DisableForwarding|^DisableForwarding" - line: 'DisableForwarding yes' + regexp: '^(#|)\s*DisableForwarding.*' + replace: 'DisableForwarding yes' - name: "4.2.8 | PATCH | Ensure sshd DisableForwarding is enabled | ensure x11 disabled" - ansible.builtin.lineinfile: + ansible.builtin.replace: path: /etc/ssh/sshd_config regexp: ^X11Forwarding (yes|no) - line: '#DisableForwarding yes' + replace: '#DisableForwarding yes' - name: "4.2.9 | PATCH | Ensure SSH HostbasedAuthentication is disabled" when: diff --git a/tasks/section_4/cis_4.4.3.4.x.yml b/tasks/section_4/cis_4.4.3.4.x.yml index 65ba5768..87dbcc0e 100644 --- a/tasks/section_4/cis_4.4.3.4.x.yml +++ b/tasks/section_4/cis_4.4.3.4.x.yml @@ -23,7 +23,6 @@ - not rhel8cis_allow_authselect_updates ansible.builtin.replace: path: "/etc/pam.d/{{ item }}-auth" - #regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)nullok(.*$) regexp: nullok replace: '' loop: From a4d11fafbdb6e1c7c7292013636d69c4f13d0e0c Mon Sep 17 00:00:00 2001 From: uk-bolly Date: Wed, 19 Jun 2024 21:41:07 +0100 Subject: [PATCH 21/62] Interactive users logic and workflow (#385) * interactive user vars updates Signed-off-by: Mark Bolwell * improved conditionals checks Signed-off-by: Mark Bolwell * Tidy up titles Signed-off-by: Mark Bolwell * updated with latest devel Signed-off-by: Mark Bolwell * removed file not required Signed-off-by: Mark Bolwell * improved logic for /dev/null home dirs Signed-off-by: Mark Bolwell * Updated workflow to new runner Signed-off-by: Mark Bolwell --------- Signed-off-by: Mark Bolwell --- .../workflows/devel_pipeline_validation.yml | 291 ++++++++++-------- .../workflows/main_pipeline_validation.yml | 277 +++++++++-------- defaults/main.yml | 6 +- tasks/prelim.yml | 70 ++--- tasks/section_1/cis_1.5.1.x.yml | 4 +- tasks/section_4/cis_4.5.1.x.yml | 4 +- tasks/section_4/cis_4.5.2.x.yml | 20 +- tasks/section_6/cis_6.1.x.yml | 6 +- tasks/section_6/cis_6.2.x.yml | 42 +-- templates/ansible_vars_goss.yml.j2 | 6 +- templates/audit/99_auditd.rules.j2 | 44 +-- 11 files changed, 379 insertions(+), 391 deletions(-) diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index 39af625a..e02fe1f0 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -1,138 +1,159 @@ --- - name: Devel pipeline - - on: # yamllint disable-line rule:truthy - pull_request_target: - types: [opened, reopened, synchronize] - branches: - - devel - paths: - - '**.yml' - - '**.sh' - - '**.j2' - - '**.ps1' - - '**.cfg' - - # A workflow run is made up of one or more jobs - # that can run sequentially or in parallel - jobs: - # This will create messages for first time contributers and direct them to the Discord server - welcome: - runs-on: ubuntu-latest - - steps: - - uses: actions/first-interaction@main - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - pr-message: |- - Congrats on opening your first pull request and thank you for taking the time to help improve Ansible-Lockdown! - Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well. - - # This workflow contains a single job that tests the playbook - playbook-test: - # The type of runner that the job will run on - runs-on: ubuntu-latest - env: - ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} - # Imported as a variable by terraform - TF_VAR_repository: ${{ github.event.repository.name }} - defaults: - run: - shell: bash - working-directory: .github/workflows/github_linux_IaC - - steps: - - name: Clone ${{ github.event.repository.name }} - uses: actions/checkout@v4 + name: Devel pipeline + + on: # yamllint disable-line rule:truthy + pull_request_target: + types: [opened, reopened, synchronize] + branches: + - devel + paths: + - '**.yml' + - '**.sh' + - '**.j2' + - '**.ps1' + - '**.cfg' + # Allow manual running of workflow + workflow_dispatch: + + # Allow permissions for AWS auth + permissions: + id-token: write + contents: read + pull-requests: read + + # A workflow run is made up of one or more jobs + # that can run sequentially or in parallel + jobs: + # This will create messages for first time contributers and direct them to the Discord server + welcome: + runs-on: self-hosted + + steps: + - uses: actions/first-interaction@main with: - ref: ${{ github.event.pull_request.head.sha }} - - # Pull in terraform code for linux servers - - name: Clone GitHub IaC plan - uses: actions/checkout@v4 - with: - repository: ansible-lockdown/github_linux_IaC - path: .github/workflows/github_linux_IaC - - - name: Add_ssh_key - working-directory: .github/workflows - env: - SSH_AUTH_SOCK: /tmp/ssh_agent.sock - PRIVATE_KEY: "${{ secrets.SSH_PRV_KEY }}" - run: | - mkdir .ssh - chmod 700 .ssh - echo $PRIVATE_KEY > .ssh/github_actions.pem - chmod 600 .ssh/github_actions.pem - - - name: DEBUG - Show IaC files - if: env.ENABLE_DEBUG == 'true' - run: | - echo "OSVAR = $OSVAR" - echo "benchmark_type = $benchmark_type" - pwd - ls - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Init - id: init - run: terraform init - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Validate - id: validate - run: terraform validate - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Apply - id: apply - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - run: terraform apply -var-file "github_vars.tfvars" -var-file "${OSVAR}.tfvars" --auto-approve -input=false - - ## Debug Section - - name: DEBUG - Show Ansible hostfile - if: env.ENABLE_DEBUG == 'true' - run: cat hosts.yml - - # Aws deployments taking a while to come up insert sleep or playbook fails - - - name: Sleep for 60 seconds - run: sleep ${{ vars.BUILD_SLEEPTIME }} - - # Run the Ansible playbook - - name: Run_Ansible_Playbook - uses: arillso/action.playbook@master - with: - playbook: site.yml - inventory: .github/workflows/github_linux_IaC/hosts.yml - galaxy_file: collections/requirements.yml - private_key: ${{ secrets.SSH_PRV_KEY }} - # verbose: 3 - env: - ANSIBLE_HOST_KEY_CHECKING: "false" - ANSIBLE_DEPRECATION_WARNINGS: "false" - - # Remove test system - User secrets to keep if necessary - - - name: Terraform_Destroy - if: always() && env.ENABLE_DEBUG == 'false' - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - run: terraform destroy -var-file "github_vars.tfvars" -var-file "${OSVAR}.tfvars" --auto-approve -input=false + repo-token: ${{ secrets.GITHUB_TOKEN }} + pr-message: |- + Congrats on opening your first pull request and thank you for taking the time to help improve Ansible-Lockdown! + Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well. + + # This workflow contains a single job that tests the playbook + playbook-test: + # The type of runner that the job will run on + runs-on: self-hosted + env: + ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} + # Imported as a variable by terraform + TF_VAR_repository: ${{ github.event.repository.name }} + AWS_REGION: "us-east-1" + ANSIBLE_VERSION: ${{ vars.ANSIBLE_RUNNER_VERSION }} + defaults: + run: + shell: bash + working-directory: .github/workflows/github_linux_IaC + # working-directory: .github/workflows + + steps: + + - name: Git clone the lockdown repository to test + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: If a variable for IAC_BRANCH is set use that branch + working-directory: .github/workflows + run: | + if [ ${{ vars.IAC_BRANCH }} != '' ]; then + echo "IAC_BRANCH=${{ vars.IAC_BRANCH }}" >> $GITHUB_ENV + echo "Pipeline using the following IAC branch ${{ vars.IAC_BRANCH }}" + else + echo IAC_BRANCH=main >> $GITHUB_ENV + fi + + + # Pull in terraform code for linux servers + - name: Clone GitHub IaC plan + uses: actions/checkout@v4 + with: + repository: ansible-lockdown/github_linux_IaC + path: .github/workflows/github_linux_IaC + ref: ${{ env.IAC_BRANCH }} + + # Uses dedicated restricted role and policy to enable this only for this task + # No credentials are part of github for AWS auth + - name: configure aws credentials + uses: aws-actions/configure-aws-credentials@main + with: + role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }} + role-session-name: ${{ secrets.AWS_ROLE_SESSION }} + aws-region: ${{ env.AWS_REGION }} + + - name: DEBUG - Show IaC files + if: env.ENABLE_DEBUG == 'true' + run: | + echo "OSVAR = $OSVAR" + echo "benchmark_type = $benchmark_type" + echo "PRIVSUBNET_ID = $AWS_PRIVSUBNET_ID" + echo "VPC_ID" = $AWS_VPC_SECGRP_ID" + pwd + ls + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + benchmark_type: ${{ vars.BENCHMARK_TYPE }} + PRIVSUBNET_ID: ${{ secrets.AWS_PRIVSUBNET_ID }} + VPC_ID: ${{ secrets.AWS_VPC_SECGRP_ID }} + + - name: Tofu init + id: init + run: tofu init + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + + - name: Tofu validate + id: validate + run: tofu validate + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + + - name: Tofu apply + id: apply + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu apply -var-file "${OSVAR}.tfvars" --auto-approve -input=false + +## Debug Section + - name: DEBUG - Show Ansible hostfile + if: env.ENABLE_DEBUG == 'true' + run: cat hosts.yml + + # Aws deployments taking a while to come up insert sleep or playbook fails + + - name: Sleep to allow system to come up + run: sleep ${{ vars.BUILD_SLEEPTIME }} + + # Run the Ansible playbook + - name: Run_Ansible_Playbook + env: + ANSIBLE_HOST_KEY_CHECKING: "false" + ANSIBLE_DEPRECATION_WARNINGS: "false" + run: | + /opt/ansible_${{ env.ANSIBLE_VERSION }}_venv/bin/ansible-playbook -i hosts.yml --private-key ~/.ssh/le_runner ../../../site.yml + + # Remove test system - User secrets to keep if necessary + + - name: Tofu Destroy + if: always() && env.ENABLE_DEBUG == 'false' + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu destroy -var-file "${OSVAR}.tfvars" --auto-approve -input=false diff --git a/.github/workflows/main_pipeline_validation.yml b/.github/workflows/main_pipeline_validation.yml index 8ded7018..4a5adc9c 100644 --- a/.github/workflows/main_pipeline_validation.yml +++ b/.github/workflows/main_pipeline_validation.yml @@ -1,127 +1,156 @@ --- - name: Main pipeline - - on: # yamllint disable-line rule:truthy - pull_request_target: - types: [opened, reopened, synchronize] - branches: - - main - paths: - - '**.yml' - - '**.sh' - - '**.j2' - - '**.ps1' - - '**.cfg' - - # A workflow run is made up of one or more jobs - # that can run sequentially or in parallel - jobs: - - # This workflow contains a single job that tests the playbook - playbook-test: - # The type of runner that the job will run on - runs-on: ubuntu-latest - env: - ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} - # Imported as a variable by terraform - TF_VAR_repository: ${{ github.event.repository.name }} - defaults: - run: - shell: bash - working-directory: .github/workflows/github_linux_IaC - - steps: - - name: Clone ${{ github.event.repository.name }} - uses: actions/checkout@v4 + name: Main pipeline + + on: # yamllint disable-line rule:truthy + pull_request_target: + types: [opened, reopened, synchronize] + branches: + - main + paths: + - '**.yml' + - '**.sh' + - '**.j2' + - '**.ps1' + - '**.cfg' + + # Allow permissions for AWS auth + permissions: + id-token: write + contents: read + pull-requests: read + + # A workflow run is made up of one or more jobs + # that can run sequentially or in parallel + jobs: + # This will create messages for first time contributers and direct them to the Discord server + welcome: + runs-on: self-hosted + + steps: + - uses: actions/first-interaction@main with: - ref: ${{ github.event.pull_request.head.sha }} - - # Pull in terraform code for linux servers - - name: Clone GitHub IaC plan - uses: actions/checkout@v4 - with: - repository: ansible-lockdown/github_linux_IaC - path: .github/workflows/github_linux_IaC - - - name: Add_ssh_key - working-directory: .github/workflows - env: - SSH_AUTH_SOCK: /tmp/ssh_agent.sock - PRIVATE_KEY: "${{ secrets.SSH_PRV_KEY }}" - run: | - mkdir .ssh - chmod 700 .ssh - echo $PRIVATE_KEY > .ssh/github_actions.pem - chmod 600 .ssh/github_actions.pem - - - name: DEBUG - Show IaC files - if: env.ENABLE_DEBUG == 'true' - run: | - echo "OSVAR = $OSVAR" - echo "benchmark_type = $benchmark_type" - pwd - ls - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Init - id: init - run: terraform init - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Validate - id: validate - run: terraform validate - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Apply - id: apply - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - run: terraform apply -var-file "github_vars.tfvars" -var-file "${OSVAR}.tfvars" --auto-approve -input=false - - ## Debug Section - - name: DEBUG - Show Ansible hostfile - if: env.ENABLE_DEBUG == 'true' - run: cat hosts.yml - - # Aws deployments taking a while to come up insert sleep or playbook fails - - - name: Sleep for 60 seconds - run: sleep ${{ vars.BUILD_SLEEPTIME }} - - # Run the Ansible playbook - - name: Run_Ansible_Playbook - uses: arillso/action.playbook@master - with: - playbook: site.yml - inventory: .github/workflows/github_linux_IaC/hosts.yml - galaxy_file: collections/requirements.yml - private_key: ${{ secrets.SSH_PRV_KEY }} - # verbose: 3 - env: - ANSIBLE_HOST_KEY_CHECKING: "false" - ANSIBLE_DEPRECATION_WARNINGS: "false" - - # Remove test system - User secrets to keep if necessary - - - name: Terraform_Destroy - if: always() && env.ENABLE_DEBUG == 'false' - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - run: terraform destroy -var-file "github_vars.tfvars" -var-file "${OSVAR}.tfvars" --auto-approve -input=false + repo-token: ${{ secrets.GITHUB_TOKEN }} + pr-message: |- + Congrats on opening your first pull request and thank you for taking the time to help improve Ansible-Lockdown! + Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well. + + # This workflow contains a single job that tests the playbook + playbook-test: + # The type of runner that the job will run on + runs-on: self-hosted + env: + ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} + # Imported as a variable by terraform + TF_VAR_repository: ${{ github.event.repository.name }} + AWS_REGION : "us-east-1" + ANSIBLE_VERSION: ${{ vars.ANSIBLE_RUNNER_VERSION }} + defaults: + run: + shell: bash + working-directory: .github/workflows/github_linux_IaC + # working-directory: .github/workflows + + steps: + + - name: Git clone the lockdown repository to test + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: If a variable for IAC_BRANCH is set use that branch + working-directory: .github/workflows + run: | + if [ ${{ vars.IAC_BRANCH }} != '' ]; then + echo "IAC_BRANCH=${{ vars.IAC_BRANCH }}" >> $GITHUB_ENV + echo "Pipeline using the following IAC branch ${{ vars.IAC_BRANCH }}" + else + echo IAC_BRANCH=main >> $GITHUB_ENV + fi + + # Pull in terraform code for linux servers + - name: Clone GitHub IaC plan + uses: actions/checkout@v4 + with: + repository: ansible-lockdown/github_linux_IaC + path: .github/workflows/github_linux_IaC + ref: ${{ env.IAC_BRANCH }} + + # Uses dedicated restricted role and policy to enable this only for this task + # No credentials are part of github for AWS auth + - name: configure aws credentials + uses: aws-actions/configure-aws-credentials@main + with: + role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }} + role-session-name: ${{ secrets.AWS_ROLE_SESSION }} + aws-region: ${{ env.AWS_REGION }} + + - name: DEBUG - Show IaC files + if: env.ENABLE_DEBUG == 'true' + run: | + echo "OSVAR = $OSVAR" + echo "benchmark_type = $benchmark_type" + echo "PRIVSUBNET_ID = $AWS_PRIVSUBNET_ID" + echo "VPC_ID" = $AWS_VPC_SECGRP_ID" + pwd + ls + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + benchmark_type: ${{ vars.BENCHMARK_TYPE }} + PRIVSUBNET_ID: ${{ secrets.AWS_PRIVSUBNET_ID }} + VPC_ID: ${{ secrets.AWS_VPC_SECGRP_ID }} + + - name: Tofu init + id: init + run: tofu init + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + + - name: Tofu validate + id: validate + run: tofu validate + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + + - name: Tofu apply + id: apply + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu apply -var-file "${OSVAR}.tfvars" --auto-approve -input=false + +## Debug Section + - name: DEBUG - Show Ansible hostfile + if: env.ENABLE_DEBUG == 'true' + run: cat hosts.yml + + # Aws deployments taking a while to come up insert sleep or playbook fails + + - name: Sleep to allow system to come up + run: sleep ${{ vars.BUILD_SLEEPTIME }} + + # Run the Ansible playbook + - name: Run_Ansible_Playbook + env: + ANSIBLE_HOST_KEY_CHECKING: "false" + ANSIBLE_DEPRECATION_WARNINGS: "false" + run: | + /opt/ansible_${{ env.ANSIBLE_VERSION }}_venv/bin/ansible-playbook -i hosts.yml --private-key ~/.ssh/le_runner ../../../site.yml + + # Remove test system - User secrets to keep if necessary + + - name: Tofu Destroy + if: always() && env.ENABLE_DEBUG == 'false' + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu destroy -var-file "${OSVAR}.tfvars" --auto-approve -input=false diff --git a/defaults/main.yml b/defaults/main.yml index 074f1258..fc91ae17 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -757,10 +757,8 @@ rhel8cis_inactivelock: # Allow ansible to expire password for account with a last changed date in the future. False will just display users in violation, true will expire those users passwords rhel8cis_futurepwchgdate_autofix: true -# This is a dynamic check but can be overridden here marking it as false and uncomment -rhel8uid_info_dynamic: true -# rhel8uid_interactive_uid_start: 1000 -# rhel8uid_interactive_uid_stop: 60000 +rhel8uid_uid_start: 1000 +rhel8uid_uid_stop: 60000 ## Section5 vars diff --git a/tasks/prelim.yml b/tasks/prelim.yml index f00e4e6d..d35cf848 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -10,37 +10,29 @@ - python3-rpm state: present -# List users in order to look files inside each home directory -# - name: "PRELIM | AUDIT | List users accounts" -# tags: -# - always -# ansible.builtin.shell: "awk -F: '{print $1}' /etc/passwd" -# changed_when: false -# check_mode: false -# register: discovered_users - -- name: "PRELIM | AUDIT | Gather interactive user ID min and max" - when: - - rhel8uid_info_dynamic +- name: "PRELIM | AUDIT | Interactive Users" tags: - always - block: - - name: "PRELIM | AUDIT | Gather interactive user ID min" - ansible.builtin.shell: grep ^UID_MIN /etc/login.defs | awk '{print $2}' - changed_when: false - failed_when: false - register: discovered_min_uid + ansible.builtin.shell: > + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false" && $7 != "/dev/null") { print $1 }' + changed_when: false + register: discovered_interactive_usernames - - name: "PRELIM | AUDIT | Gather interactive user ID max" - ansible.builtin.shell: grep ^UID_MAX /etc/login.defs | awk '{print $2}' - changed_when: false - failed_when: false - register: discovered_max_uid +- name: "PRELIM | AUDIT | Interactive User accounts home directories" + tags: + - always + ansible.builtin.shell: > + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false" && $7 != "/dev/null") { print $6 }' + changed_when: false + register: discovered_interactive_users_home - - name: "PRELIM | AUDIT | Setting the fact" - ansible.builtin.set_fact: - rhel8uid_interactive_uid_start: "{{ discovered_min_uid.stdout | string }}" - rhel8uid_interactive_uid_stop: "{{ discovered_max_uid.stdout | string }}" +- name: "PRELIM | AUDIT | Interactive UIDs" + tags: + - always + ansible.builtin.shell: > + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $3 }' + changed_when: false + register: discovered_interactive_uids - name: "PRELIM | AUDIT | Set facts based on boot type" tags: @@ -127,6 +119,7 @@ register: discovered_systemd_coredump - name: "PRELIM | AUDIT | Ensure crypto-policies-scripts package is installed" + when: "'crypto-policies-scripts' not in ansible_facts.packages" tags: - always ansible.builtin.package: @@ -164,6 +157,7 @@ state: present - name: "PRELIM | PATCH | Cron Package" + when: "'cronie' not in ansible_facts.packages" tags: - always ansible.builtin.package: @@ -195,12 +189,12 @@ ansible.builtin.set_fact: authselect_version: OK - - name: "PRELIM | WARN | Check authselect package versions | Warning" + - name: "PRELIM | WARNING | Check authselect package versions | Warning" when: ansible_facts.packages.authselect[0].version is version(authselect_pkg_version, '<') ansible.builtin.debug: msg: "Warning!! Authselect controls won't run as authselect pkg version too low" - - name: "PRELIM | WARN | Check authselect package versions | Warning" + - name: "PRELIM | WARNING | Check authselect package versions | Warning" when: ansible_facts.packages.authselect[0].version is version(authselect_pkg_version, '<') ansible.builtin.import_tasks: file: warning_facts.yml @@ -220,14 +214,14 @@ ansible.builtin.set_fact: pam_version: OK - - name: "PRELIM | WARN | Check pam package versions | Warning" + - name: "PRELIM | WARNING | Check pam package versions | Warning" when: - ansible_facts.packages.pam[0].version is version(pam_pkg_version, '<') - ansible_facts.packages.pam[0].release is version (pam_pkg_release, '<') ansible.builtin.debug: msg: "Warning!! Authselect controls won't run as pam package version too low" - - name: "PRELIM | WARN | Check pam package versions | Warning" + - name: "PRELIM | WARNING | Check pam package versions | Warning" when: - ansible_facts.packages.pam[0].version is version(pam_pkg_version, '<') - ansible_facts.packages.pam[0].release is version (pam_pkg_release, '<') @@ -287,7 +281,9 @@ register: discovered_interactive_users_home - name: "PRELIM | PATCH | Section 5.1 | Configure System Accounting (auditd)" - when: rhel8cis_level_2 + when: + - rhel8cis_level_2 + - "'audit' not in ansible_facts.packages" tags: - always ansible.builtin.package: @@ -334,16 +330,6 @@ patterns: '*.conf,*.rules' register: discovered_auditd_conf_files -# - name: "PRELIM | AUDIT | Gather accounts with empty password fields" -# when: -# - rhel8cis_rule_6_2_1 -# tags: -# - always -# ansible.builtin.shell: "cat /etc/shadow | awk -F: '($2 == \"\" ) {j++;print $1; } END {exit j}'" -# changed_when: false -# check_mode: false -# register: discovered_empty_password_accounts - - name: "PRELIM | AUDIT | Gather UID 0 accounts other than root" when: - rhel8cis_rule_6_2_8 diff --git a/tasks/section_1/cis_1.5.1.x.yml b/tasks/section_1/cis_1.5.1.x.yml index 8a24f695..971c336c 100644 --- a/tasks/section_1/cis_1.5.1.x.yml +++ b/tasks/section_1/cis_1.5.1.x.yml @@ -106,14 +106,14 @@ failed_when: false changed_when: false - - name: "1.5.1.6 | WARN | Ensure no unconfined services exist | Message on unconfined services" + - name: "1.5.1.6 | WARNING | Ensure no unconfined services exist | Message on unconfined services" when: - discovered_unconf_services is defined - discovered_unconf_services.stdout | length > 0 ansible.builtin.debug: msg: "Warning!! You have unconfined services: {{ discovered_unconf_services.stdout_lines }}" - - name: "1.5.1.6 | WARN | Ensure no unconfined services exist | warning count" + - name: "1.5.1.6 | WARNING | Ensure no unconfined services exist | warning count" when: - discovered_unconf_services is defined - discovered_unconf_services.stdout | length > 0 diff --git a/tasks/section_4/cis_4.5.1.x.yml b/tasks/section_4/cis_4.5.1.x.yml index 49a3c3f8..619e69a1 100644 --- a/tasks/section_4/cis_4.5.1.x.yml +++ b/tasks/section_4/cis_4.5.1.x.yml @@ -179,7 +179,7 @@ failed_when: discovered_users_user_future.rc not in [ 0, 1 ] register: discovered_users_user_future - - name: "4.5.1.5 | WARN | Ensure inactive password lock is 30 days or less | Warn Users in future" + - name: "4.5.1.5 | WARNING | Ensure inactive password lock is 30 days or less | Warn Users in future" when: - discovered_users_user_future is defined - discovered_users_user_future.stdout | length > 0 @@ -188,7 +188,7 @@ - "Warning!! - The following users have passwords set in the future please investigate" - "{{ discovered_users_user_future.stdout_lines }}" - - name: "4.5.1.5 | WARN | Ensure inactive password lock is 30 days or less | Warn Users in future" + - name: "4.5.1.5 | WARNING | Ensure inactive password lock is 30 days or less | Warn Users in future" when: - rhel8cis_users_user_future is defined - rhel8cis_users_user_future.stdout | length > 0 diff --git a/tasks/section_4/cis_4.5.2.x.yml b/tasks/section_4/cis_4.5.2.x.yml index 8a44c2b0..1a2eae1a 100644 --- a/tasks/section_4/cis_4.5.2.x.yml +++ b/tasks/section_4/cis_4.5.2.x.yml @@ -53,14 +53,8 @@ block: - name: "4.5.2.3 | PATCH | | Ensure system accounts are secured | Set nologin" when: - - item.id != "root" - - item.id != "sync" - - item.id != "shutdown" - - item.id != "halt" - - item.id != "nfsnobody" - - item.uid < discovered_min_uid.stdout | int - - item.shell != " /bin/false" - - item.shell != " /usr/sbin/nologin" + - item.id not in discovered_interactive_usernames.stdout + - "'root' not in item.id" ansible.builtin.user: name: "{{ item.id }}" shell: /usr/sbin/nologin @@ -70,14 +64,8 @@ - name: "4.5.2.3 | PATCH | | Ensure system accounts are secured | Lock accounts" when: - - item.id != "root" - - item.id != "sync" - - item.id != "shutdown" - - item.id != "halt" - - item.id != "nfsnobody" - - item.uid < discovered_min_uid.stdout | int - - item.shell != " /bin/false" - - item.shell != " /usr/sbin/nologin" + - "item.id not in discovered_interactive_usernames.stdout" + - "'root' not in item.id" ansible.builtin.user: name: "{{ item.id }}" password_lock: true diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 6e4d166a..0c16bd2f 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -352,7 +352,7 @@ - rhel8cis_sgid_adjust - discovered_sgid_executables_flatten | length > 0 - - name: "6.1.13 | WARN | Ensure SUID and SGID files are reviewed | Alert SUID executables exist" + - name: "6.1.13 | WARNING | Ensure SUID and SGID files are reviewed | Alert SUID executables exist" when: - discovered_suid_executables_flatten | length > 0 - not rhel8cis_suid_adjust @@ -362,7 +362,7 @@ - "The files are listed below, please confirm the integrity of these binaries" - "{{ discovered_suid_executables_flatten }}" - - name: "6.1.13 | WARN | Ensure SUID and SGID files are reviewed | Alert SGID executables exist" + - name: "6.1.13 | WARNING | Ensure SUID and SGID files are reviewed | Alert SGID executables exist" when: - discovered_sgid_executables_flatten | length > 0 - not rhel8cis_sgid_adjust @@ -372,7 +372,7 @@ - "The files are listed below, please review the integrity of these binaries" - "{{ discovered_sgid_executables_flatten }}" - - name: "6.1.13 | WARN | Ensure SUID and SGID files are reviewed | Warn Count" + - name: "6.1.13 | WARNING | Ensure SUID and SGID files are reviewed | Warn Count" when: - (discovered_suid_executables_flatten | length > 0 and not rhel8cis_suid_adjust) or (discovered_sgid_executables_flatten | length > 0 and not rhel8cis_sgid_adjust) diff --git a/tasks/section_6/cis_6.2.x.yml b/tasks/section_6/cis_6.2.x.yml index 6a33eb4e..24fe621b 100644 --- a/tasks/section_6/cis_6.2.x.yml +++ b/tasks/section_6/cis_6.2.x.yml @@ -27,7 +27,7 @@ - "Warning!! You have users that are not using a shadowed password. Please convert the below accounts to use a shadowed password" - "{{ discovered_nonshadowed_users.stdout_lines }}" - - name: "6.2.1 | WARN | Ensure accounts in /etc/passwd use shadowed passwords | warn_count" + - name: "6.2.1 | WARNING | Ensure accounts in /etc/passwd use shadowed passwords | warn_count" when: discovered_nonshadowed_users.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml @@ -89,7 +89,7 @@ ansible.builtin.debug: msg: "Warning!! The following users have non-existent GIDs (Groups): {{ discovered_passwd_gid_check.stdout_lines | join (', ') }}" - - name: "6.2.3 | WARN | Ensure all groups in /etc/passwd exist in /etc/group | warn_count" + - name: "6.2.3 | WARNING | Ensure all groups in /etc/passwd exist in /etc/group | warn_count" when: discovered_passwd_gid_check.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml @@ -189,12 +189,12 @@ check_mode: false register: discovered_username_check - - name: "6.2.6 | WARN | Ensure no duplicate user names exist | Print warning about users with duplicate User Names" + - name: "6.2.6 | WARNING | Ensure no duplicate user names exist | Print warning about users with duplicate User Names" when: discovered_username_check.stdout | length > 0 ansible.builtin.debug: msg: "Warning!! The following user names are duplicates: {{ discovered_user_username_check.stdout_lines }}" - - name: "6.2.6 | WARN | Ensure no duplicate user names exist | Set warning count" + - name: "6.2.6 | WARNING | Ensure no duplicate user names exist | Set warning count" when: discovered_username_check.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml @@ -342,39 +342,7 @@ state: directory owner: "{{ item.id }}" group: "{{ item.gid }}" - register: discovered_home_dirs - loop: "{{ rhel8cis_passwd | selectattr('uid', '>=', discovered_min_uid.stdout | int ) | selectattr('uid', '<=', discovered_max_uid.stdout | int ) | list }}" - loop_control: - label: "{{ item.id }}" - - - name: "6.2.10 | AUDIT | Ensure local interactive user home directories exist | Get perms stat" - ansible.builtin.stat: - path: "{{ item }}" - register: discovered_home_dir_perms - loop: "{{ discovered_interactive_users_home.stdout_lines }}" - - - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Set perms if needed" - ansible.builtin.file: - path: "{{ item.stat.path }}" - state: directory - mode: g-w,o-rwx - loop: "{{ discovered_home_dir_perms.results }}" - loop_control: - label: "{{ item }}" - - - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Own their home directories" - when: - - item.uid >= discovered_min_uid.stdout | int - - item.id != 'nobody' - - (item.id != 'tss' and item.dir != '/dev/null') - - item.shell != '/sbin/nologin' - - "'bin/nologin' not in item.shell" - - "'bin/false' not in item.shell" - ansible.builtin.file: - path: "{{ item.dir }}" - owner: "{{ item.id }}" - state: directory - loop: "{{ rhel8cis_passwd | selectattr('uid', '>=', discovered_min_uid.stdout | int ) | selectattr('uid', '<=', discovered_max_uid.stdout | int ) | list }}" + loop: "{{ rhel8cis_passwd | selectattr('uid', '>=', rhel8uid_uid_start | int ) | selectattr('uid', '<=', rhel8uid_uid_stop | int ) | list }}" loop_control: label: "{{ item.id }}" diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index dd87431c..04a487bc 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -670,10 +670,8 @@ rhel8cis_inactivelock: # 5.6.1.5 Allow ansible to expire password for account with a last changed date in the future. False will just display users in violation, true will expire those users passwords rhel8cis_futurepwchgdate_autofix: {{ rhel8cis_futurepwchgdate_autofix }} -# This is a dynamic check but can be overridden here marking it as false and uncomment -rhel8uid_info_dynamic: "{{ rhel8uid_info_dynamic }}" -# rhel8uid_interactive_uid_start: {{ rhel8uid_interactive_uid_start }} -# rhel8uid_interactive_uid_stop: {{ rhel8uid_interactive_uid_stop }} +rhel8uid_uid_start: {{ rhel8uid_uid_start }} +rhel8uid_uid_stop: {{ rhel8uid_uid_stop }} ## Section5 vars diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index ede69166..9dd63740 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -28,14 +28,14 @@ {% endif %} {% if rhel8cis_rule_5_2_3_6 %} {% for proc in discovered_privilege_procs.stdout_lines -%} --a always,exit -F path={{ proc }} -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k privileged +-a always,exit -F path={{ proc }} -F perm=x -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k privileged {% endfor %} {% endif %} {% if rhel8cis_rule_5_2_3_7 %} --a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=access --a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=access --a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=access --a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=access +-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=access +-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=access +-a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=access +-a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=access {% endif %} {% if rhel8cis_rule_5_2_3_8 %} -w /etc/group -p wa -k identity @@ -45,16 +45,16 @@ -w /etc/security/opasswd -p wa -k identity {% endif %} {% if rhel8cis_rule_5_2_3_9 %} --a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=perm_mod {% endif %} {% if rhel8cis_rule_5_2_3_10 %} --a always,exit -F arch=b32 -S mount -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k mounts --a always,exit -F arch=b64 -S mount -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k mounts +-a always,exit -F arch=b32 -S mount -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k mounts +-a always,exit -F arch=b64 -S mount -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k mounts {% endif %} {% if rhel8cis_rule_5_2_3_11 %} -w /var/run/utmp -p wa -k session @@ -66,29 +66,29 @@ -w /var/run/faillock -p wa -k logins {% endif %} {% if rhel8cis_rule_5_2_3_13 %} --a always,exit -F arch=b64 -S unlink,unlinkat,rename,renameat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=delete --a always,exit -F arch=b32 -S unlink,unlinkat,rename,renameat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=delete +-a always,exit -F arch=b64 -S unlink,unlinkat,rename,renameat -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=delete +-a always,exit -F arch=b32 -S unlink,unlinkat,rename,renameat -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=delete {% endif %} {% if rhel8cis_rule_5_2_3_14 %} -w /etc/selinux/ -p wa -k MAC-policy -w /usr/share/selinux/ -p wa -k MAC-policy {% endif %} {% if rhel8cis_rule_5_2_3_15 %} --a always,exit -F path=/usr/bin/chcon -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k perm_chng +-a always,exit -F path=/usr/bin/chcon -F perm=x -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k perm_chng {% endif %} {% if rhel8cis_rule_5_2_3_16 %} --a always,exit -F path=/usr/bin/setfacl -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k perm_chng +-a always,exit -F path=/usr/bin/setfacl -F perm=x -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k perm_chng {% endif %} {% if rhel8cis_rule_5_2_3_17 %} --a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k perm_chng +-a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k perm_chng {% endif %} {% if rhel8cis_rule_5_2_3_18 %} --a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k usermod +-a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k usermod {% endif %} {% if rhel8cis_rule_5_2_3_19 %} --a always,exit -F arch=b32 -S init_module,finit_module,delete_module,create_module,query_module -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k kernel_modules --a always,exit -F arch=b64 -S init_module,finit_module,delete_module,create_module,query_module -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k kernel_modules --a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k kernel_modules +-a always,exit -F arch=b32 -S init_module,finit_module,delete_module,create_module,query_module -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k kernel_modules +-a always,exit -F arch=b64 -S init_module,finit_module,delete_module,create_module,query_module -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k kernel_modules +-a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k kernel_modules {% endif %} {% if rhel8cis_rule_5_2_3_20 %} -e 2 From 6b2456aa02bd489118c84fc418541cbb54d784cb Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 24 Jun 2024 16:19:15 +0100 Subject: [PATCH 22/62] updated pre-commit Signed-off-by: Mark Bolwell --- .config/.secrets.baseline | 119 -------------------------------------- .pre-commit-config.yaml | 6 +- 2 files changed, 1 insertion(+), 124 deletions(-) delete mode 100644 .config/.secrets.baseline diff --git a/.config/.secrets.baseline b/.config/.secrets.baseline deleted file mode 100644 index 65908eb9..00000000 --- a/.config/.secrets.baseline +++ /dev/null @@ -1,119 +0,0 @@ -{ - "version": "1.4.0", - "plugins_used": [ - { - "name": "ArtifactoryDetector" - }, - { - "name": "AWSKeyDetector" - }, - { - "name": "AzureStorageKeyDetector" - }, - { - "name": "Base64HighEntropyString", - "limit": 4.5 - }, - { - "name": "BasicAuthDetector" - }, - { - "name": "CloudantDetector" - }, - { - "name": "DiscordBotTokenDetector" - }, - { - "name": "GitHubTokenDetector" - }, - { - "name": "HexHighEntropyString", - "limit": 3.0 - }, - { - "name": "IbmCloudIamDetector" - }, - { - "name": "IbmCosHmacDetector" - }, - { - "name": "JwtTokenDetector" - }, - { - "name": "KeywordDetector", - "keyword_exclude": "" - }, - { - "name": "MailchimpDetector" - }, - { - "name": "NpmDetector" - }, - { - "name": "PrivateKeyDetector" - }, - { - "name": "SendGridDetector" - }, - { - "name": "SlackDetector" - }, - { - "name": "SoftlayerDetector" - }, - { - "name": "SquareOAuthDetector" - }, - { - "name": "StripeDetector" - }, - { - "name": "TwilioKeyDetector" - } - ], - "filters_used": [ - { - "path": "detect_secrets.filters.allowlist.is_line_allowlisted" - }, - { - "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies", - "min_level": 2 - }, - { - "path": "detect_secrets.filters.heuristic.is_indirect_reference" - }, - { - "path": "detect_secrets.filters.heuristic.is_likely_id_string" - }, - { - "path": "detect_secrets.filters.heuristic.is_lock_file" - }, - { - "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string" - }, - { - "path": "detect_secrets.filters.heuristic.is_potential_uuid" - }, - { - "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign" - }, - { - "path": "detect_secrets.filters.heuristic.is_sequential_string" - }, - { - "path": "detect_secrets.filters.heuristic.is_swagger_file" - }, - { - "path": "detect_secrets.filters.heuristic.is_templated_secret" - }, - { - "path": "detect_secrets.filters.regex.should_exclude_file", - "pattern": [ - ".config/.gitleaks-report.json", - "tasks/parse_etc_password.yml" - ] - } - ], - "results": {}, - "generated_at": "2023-09-25T16:05:28Z" -} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1e9eee39..757fa792 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,15 +33,11 @@ repos: rev: v1.5.0 hooks: - id: detect-secrets - args: ['--baseline', '.config/.secrets.baseline'] - exclude: package.lock.json - repo: https://github.com/gitleaks/gitleaks - rev: v8.18.4 + rev: v8.18.3 hooks: - id: gitleaks - args: ['--baseline-path', '.config/.gitleaks-report.json'] - exclude: .config/.secrets.baseline - repo: https://github.com/ansible-community/ansible-lint rev: v24.6.0 From 318d4bd62ac0d1ee66fd17ea1a485a65dbcbcaa7 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 24 Jun 2024 16:29:18 +0100 Subject: [PATCH 23/62] issue #387 thanks to @csabapatyi Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.1.4.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_5/cis_5.1.4.yml b/tasks/section_5/cis_5.1.4.yml index bd20b407..6699f01c 100644 --- a/tasks/section_5/cis_5.1.4.yml +++ b/tasks/section_5/cis_5.1.4.yml @@ -31,7 +31,7 @@ mode: '0640' loop: "{{ discovered_logfiles_flattened }}" when: - - rhel8cis_5_1_4_logfiles_flattened is defined + - discovered_logfiles_flattened is defined - item != "/var/log/btmp" - item != "/var/log/utmp" - item != "/var/log/wtmp" From 49872792e2b6b58e200e6f2f1f7a0f1d91c7176a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 24 Jun 2024 16:39:28 +0100 Subject: [PATCH 24/62] updated workflow titles Signed-off-by: Mark Bolwell --- .github/workflows/devel_pipeline_validation.yml | 14 +++++++------- .github/workflows/main_pipeline_validation.yml | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index e02fe1f0..07eae733 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -55,7 +55,7 @@ steps: - - name: Git clone the lockdown repository to test + - name: Git Clone the Lockdown Repository to test uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} @@ -81,7 +81,7 @@ # Uses dedicated restricted role and policy to enable this only for this task # No credentials are part of github for AWS auth - - name: configure aws credentials + - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@main with: role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }} @@ -104,7 +104,7 @@ PRIVSUBNET_ID: ${{ secrets.AWS_PRIVSUBNET_ID }} VPC_ID: ${{ secrets.AWS_VPC_SECGRP_ID }} - - name: Tofu init + - name: Tofu Init id: init run: tofu init env: @@ -112,7 +112,7 @@ OSVAR: ${{ vars.OSVAR }} TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - name: Tofu validate + - name: Tofu Validate id: validate run: tofu validate env: @@ -120,7 +120,7 @@ OSVAR: ${{ vars.OSVAR }} TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - name: Tofu apply + - name: Tofu Apply id: apply env: OSVAR: ${{ vars.OSVAR }} @@ -136,11 +136,11 @@ # Aws deployments taking a while to come up insert sleep or playbook fails - - name: Sleep to allow system to come up + - name: Sleep - Allow system to come up run: sleep ${{ vars.BUILD_SLEEPTIME }} # Run the Ansible playbook - - name: Run_Ansible_Playbook + - name: Run Ansible Playbook env: ANSIBLE_HOST_KEY_CHECKING: "false" ANSIBLE_DEPRECATION_WARNINGS: "false" diff --git a/.github/workflows/main_pipeline_validation.yml b/.github/workflows/main_pipeline_validation.yml index 4a5adc9c..08433d90 100644 --- a/.github/workflows/main_pipeline_validation.yml +++ b/.github/workflows/main_pipeline_validation.yml @@ -53,7 +53,7 @@ steps: - - name: Git clone the lockdown repository to test + - name: Git Clone the Lockdown Repository to test uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} @@ -78,7 +78,7 @@ # Uses dedicated restricted role and policy to enable this only for this task # No credentials are part of github for AWS auth - - name: configure aws credentials + - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@main with: role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }} @@ -101,7 +101,7 @@ PRIVSUBNET_ID: ${{ secrets.AWS_PRIVSUBNET_ID }} VPC_ID: ${{ secrets.AWS_VPC_SECGRP_ID }} - - name: Tofu init + - name: Tofu Init id: init run: tofu init env: @@ -109,7 +109,7 @@ OSVAR: ${{ vars.OSVAR }} TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - name: Tofu validate + - name: Tofu Validate id: validate run: tofu validate env: @@ -117,7 +117,7 @@ OSVAR: ${{ vars.OSVAR }} TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - name: Tofu apply + - name: Tofu Apply id: apply env: OSVAR: ${{ vars.OSVAR }} @@ -133,11 +133,11 @@ # Aws deployments taking a while to come up insert sleep or playbook fails - - name: Sleep to allow system to come up + - name: Sleep - Allow system to come up run: sleep ${{ vars.BUILD_SLEEPTIME }} # Run the Ansible playbook - - name: Run_Ansible_Playbook + - name: Run Ansible Playbook env: ANSIBLE_HOST_KEY_CHECKING: "false" ANSIBLE_DEPRECATION_WARNINGS: "false" From 63968819d9a0a73f3d533ab19418b615d2a3c21b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 17:47:02 +0000 Subject: [PATCH 25/62] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v24.6.0 → v24.6.1](https://github.com/ansible-community/ansible-lint/compare/v24.6.0...v24.6.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1e9eee39..d965a98d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -44,7 +44,7 @@ repos: exclude: .config/.secrets.baseline - repo: https://github.com/ansible-community/ansible-lint - rev: v24.6.0 + rev: v24.6.1 hooks: - id: ansible-lint name: Ansible-lint From c48a13fc12830d4714d2d5361f759aaea84a5631 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 26 Jun 2024 09:12:02 +0100 Subject: [PATCH 26/62] updated inline with #390 thanks to @txdavec Signed-off-by: Mark Bolwell --- tasks/section_2/cis_2.2.x.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasks/section_2/cis_2.2.x.yml b/tasks/section_2/cis_2.2.x.yml index 7d559a1f..3860862a 100644 --- a/tasks/section_2/cis_2.2.x.yml +++ b/tasks/section_2/cis_2.2.x.yml @@ -393,7 +393,7 @@ - not rhel8cis_rpc_server - not rhel8cis_rpc_mask ansible.builtin.package: - name: cups + name: rpcbind state: absent - name: "2.2.12 | PATCH | Ensure rpcbind services are not in use | Mask service" @@ -464,7 +464,7 @@ - not rhel8cis_net_snmp_server - not rhel8cis_net_snmp_mask ansible.builtin.package: - name: rsync-daemon + name: net-snmp state: absent - name: "2.2.14 | PATCH | Ensure snmp services are not in use | Mask service" @@ -565,7 +565,7 @@ - not rhel8cis_squid_server - not rhel8cis_squid_mask ansible.builtin.package: - name: tftp-server + name: squid state: absent - name: "2.2.17 | PATCH | Ensure web proxy server services are not in use | Mask service" @@ -653,7 +653,7 @@ - not rhel8cis_xinetd_server - not rhel8cis_xinetd_mask ansible.builtin.package: - name: tftp-server + name: xinetd state: absent - name: "2.2.19 | PATCH | Ensure xinetd services are not in use | Mask service" From 3c0aa76923f6bb4fa8955280bcab9d666e8a8da4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 17:56:45 +0000 Subject: [PATCH 27/62] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.18.3 → v8.18.4](https://github.com/gitleaks/gitleaks/compare/v8.18.3...v8.18.4) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 06e2f319..9e462a37 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.18.3 + rev: v8.18.4 hooks: - id: gitleaks From 1b4cfd9d60c12a0be95c05540022142a706bd667 Mon Sep 17 00:00:00 2001 From: Shawn Hardwick Date: Wed, 3 Jul 2024 19:07:28 -0400 Subject: [PATCH 28/62] Fix idempotency of rule 1.6.1; Modify behavior of changed_when if reboot is pending and skipped to allow idempotency to succeed Signed-off-by: Shawn Hardwick --- defaults/main.yml | 3 +++ tasks/post.yml | 2 +- tasks/section_1/cis_1.6.x.yml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index fc91ae17..9507a83d 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -37,6 +37,9 @@ benchmark_version: v3.0.0 # Whether to skip the reboot skip_reboot: true +# Modify behavior of changed_when if reboot is pending and skipped to allow idempotency to succeed +reboot_warning_changed_when: true + ### ### Settings for associated Audit role using Goss ### diff --git a/tasks/post.yml b/tasks/post.yml index d981fcf8..88618abd 100644 --- a/tasks/post.yml +++ b/tasks/post.yml @@ -23,7 +23,7 @@ - skip_reboot ansible.builtin.debug: msg: "Warning!! changes have been made that require a reboot to be implemented but skip reboot was set - Can affect compliance check results" - changed_when: true + changed_when: reboot_warning_changed_when - name: "POST | Warning a reboot required but skip option set | warning count" when: diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml index 41712b29..4e619c49 100644 --- a/tasks/section_1/cis_1.6.x.yml +++ b/tasks/section_1/cis_1.6.x.yml @@ -18,7 +18,7 @@ - name: "1.6.1 | PATCH | Ensure system-wide crypto policy is not legacy" when: - - discovered_system_wide_crypto_policy.stdout not in rhel8cis_crypto_policy + - rhel8cis_full_crypto_policy not in discovered_system_wide_crypto_policy.stdout ansible.builtin.shell: | update-crypto-policies --set "{{ rhel8cis_full_crypto_policy }}" update-crypto-policies From c3f52d15df5c3ef474d027e7cf25e94fd42a532f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 12 Jul 2024 11:00:49 +0100 Subject: [PATCH 29/62] tidy up remove jmespath req Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.1.4.yml | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/tasks/section_5/cis_5.1.4.yml b/tasks/section_5/cis_5.1.4.yml index 6699f01c..ef2ee18c 100644 --- a/tasks/section_5/cis_5.1.4.yml +++ b/tasks/section_5/cis_5.1.4.yml @@ -13,25 +13,28 @@ - rule_5.1.4 block: - name: "5.1.4 | AUDIT | Ensure permissions on all logfiles are configured | find files" - ansible.builtin.shell: find /var/log/ -type f -perm /g+wx,o+rwx -exec ls {} \; + ansible.builtin.shell: find /var/log/ -type f -exec ls {} \; changed_when: false failed_when: false register: discovered_logfiles - - name: "5.1.4 | AUDIT | Ensure permissions on all logfiles are configured | set_fact" - ansible.builtin.set_fact: - discovered_logfiles_flattened: "{{ discovered_logfiles | json_query('stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] - when: - - discovered_logfiles.stdout_lines | length > 0 - - discovered_logfiles is defined - - name: "5.1.4 | PATCH | Ensure permissions on all logfiles are configured | change permissions" - ansible.builtin.file: - path: "{{ item }}" - mode: '0640' - loop: "{{ discovered_logfiles_flattened }}" when: - - discovered_logfiles_flattened is defined - item != "/var/log/btmp" - item != "/var/log/utmp" - item != "/var/log/wtmp" + - item != "/var/log/lastlog" + ansible.builtin.file: + path: "{{ item }}" + mode: u-x,g-wx,o-rwx + loop: "{{ discovered_logfiles.stdout_lines }}" + + - name: "5.1.4 | PATCH | Ensure permissions on all logfiles are configured | change permissions" + ansible.builtin.file: + path: "{{ item.name }}" + mode: ('ug-x,o-wx') + with_fileglob: + - /var/log/*tmp.*" + - /var/log/lastlog" + - /var/log/ssd*" + - /var/log/SSD*" From 4a2f0f445d841a33576d0245d1f481098d35a544 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 12 Jul 2024 11:03:57 +0100 Subject: [PATCH 30/62] update to audit summary jmespath req removed Signed-off-by: Mark Bolwell --- tasks/post_remediation_audit.yml | 24 +++++++++++------------- tasks/pre_remediation_audit.yml | 31 +++++++++++++++---------------- vars/audit.yml | 4 ++-- 3 files changed, 28 insertions(+), 31 deletions(-) diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 19dff268..d58e9217 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -8,7 +8,7 @@ AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" AUDIT_FILE: goss.yml -- name: Post Audit | Ensure audit files readable by users +- name: Post Audit | ensure audit files readable by users ansible.builtin.file: path: "{{ item }}" mode: '0644' @@ -21,26 +21,24 @@ when: - audit_format == "json" block: - - name: Post Audit | Capture data {{ post_audit_outfile }} - ansible.builtin.shell: "cat {{ post_audit_outfile }}" - register: discovered_post_audit + - name: Post Audit | Capture audit data if json format + ansible.builtin.shell: grep -E '"summary-line.*Count:.*Failed' "{{ post_audit_outfile }}" | cut -d'"' -f4 + register: post_audit_summary changed_when: false - - name: Post Audit | Capture post-audit result + - name: Post Audit | Set Fact for audit summary ansible.builtin.set_fact: - post_audit_summary: "{{ discovered_post_audit.stdout | from_json | json_query(summary) }}" - vars: - summary: summary."summary-line" + post_audit_results: "{{ post_audit_summary.stdout }}" - name: Post Audit | Capture audit data if documentation format when: - audit_format == "documentation" block: - - name: Post Audit | Capture data {{ post_audit_outfile }} - ansible.builtin.shell: "tail -2 {{ post_audit_outfile }}" - register: discovered_post_audit + - name: Post Audit | Capture audit data if documentation format + ansible.builtin.shell: "tail -2 /opt/audit_ubuntu2204-CIS-UBUNTU22_1720624848.documentation" + register: post_audit_summary changed_when: false - - name: Post Audit | Capture post-audit result + - name: Post Audit | Set Fact for audit summary ansible.builtin.set_fact: - post_audit_summary: "{{ discovered_post_audit.stdout_lines }}" + post_audit_results: "{{ post_audit_summary.stdout }}" diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index fb6d709f..a745826f 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -60,19 +60,20 @@ - name: Pre Audit Setup | Check for goss file ansible.builtin.stat: path: "{{ audit_bin }}" - register: discovered_goss_available + register: goss_available - name: Pre Audit Setup | If audit ensure goss is available + when: + - not goss_available.stat.exists ansible.builtin.assert: - that: discovered_goss_available.stat.exists msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}" - name: Pre Audit Setup | Copy ansible default vars values to test audit - when: - - run_audit tags: - goss_template - run_audit + when: + - run_audit ansible.builtin.template: src: ansible_vars_goss.yml.j2 dest: "{{ audit_vars_path }}" @@ -90,29 +91,27 @@ when: - audit_format == "json" block: - - name: Pre Audit | Capture data {{ pre_audit_outfile }} - ansible.builtin.shell: "cat {{ pre_audit_outfile }}" - register: discovered_pre_audit + - name: Pre Audit | Capture audit data if json format + ansible.builtin.shell: grep -E '\"summary-line.*Count:.*Failed' "{{ pre_audit_outfile }}" | cut -d'"' -f4 + register: pre_audit_summary changed_when: false - - name: Pre Audit | Capture pre-audit result + - name: Pre Audit | Set Fact for audit summary ansible.builtin.set_fact: - pre_audit_summary: "{{ discovered_pre_audit.stdout | from_json | json_query(summary) }}" - vars: - summary: summary."summary-line" + pre_audit_results: "{{ pre_audit_summary.stdout }}" - name: Pre Audit | Capture audit data if documentation format when: - audit_format == "documentation" block: - - name: Pre Audit | Capture data {{ pre_audit_outfile }} | documentation format - ansible.builtin.shell: "tail -2 {{ pre_audit_outfile }}" - register: discovered_pre_audit + - name: Pre Audit | Capture audit data if documentation format + ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' + register: pre_audit_summary changed_when: false - - name: Pre Audit | Capture pre-audit result | documentation format + - name: Pre Audit | Set Fact for audit summary ansible.builtin.set_fact: - pre_audit_summary: "{{ discovered_pre_audit.stdout_lines }}" + pre_audit_results: "{{ pre_audit_summary.stdout }}" - name: Audit_Only | Run Audit Only when: diff --git a/vars/audit.yml b/vars/audit.yml index bb50f6d3..9dc666a6 100644 --- a/vars/audit.yml +++ b/vars/audit.yml @@ -34,7 +34,7 @@ audit_format: json audit_vars_path: "{{ audit_conf_dir }}/vars/{{ ansible_facts.hostname }}.yml" audit_results: | - The audit results are: {{ pre_audit_summary }} - {% if not audit_only %}The post remediation audit results are: {{ post_audit_summary }}{% endif %} + The{% if not audit_only %} pre remediation{% endif %} audit results are: {{ pre_audit_results}} + {% if not audit_only %}The post remediation audit results are: {{ post_audit_results }}{% endif %} Full breakdown can be found in {{ audit_log_dir }} From a54c85cc969a7af8d46649f760e27e2ad7c18dfd Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 12 Jul 2024 14:00:37 +0100 Subject: [PATCH 31/62] updated layout Signed-off-by: Mark Bolwell --- tasks/post_remediation_audit.yml | 2 +- tasks/pre_remediation_audit.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index d58e9217..ea72759c 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -8,7 +8,7 @@ AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" AUDIT_FILE: goss.yml -- name: Post Audit | ensure audit files readable by users +- name: Post Audit | Ensure audit files readable by users ansible.builtin.file: path: "{{ item }}" mode: '0644' diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index a745826f..c72136d2 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -69,11 +69,11 @@ msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}" - name: Pre Audit Setup | Copy ansible default vars values to test audit + when: + - run_audit tags: - goss_template - run_audit - when: - - run_audit ansible.builtin.template: src: ansible_vars_goss.yml.j2 dest: "{{ audit_vars_path }}" From db542efb77b6389828a655c3dd3f7b8c4cd8572c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 17:49:47 +0000 Subject: [PATCH 32/62] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v24.6.1 → v24.7.0](https://github.com/ansible-community/ansible-lint/compare/v24.6.1...v24.7.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9e462a37..e3bd1700 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,7 @@ repos: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v24.6.1 + rev: v24.7.0 hooks: - id: ansible-lint name: Ansible-lint From 77bfb923cfef75e4d41a4aa8465f0ed23fd57e6b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 19 Jul 2024 08:31:54 +0100 Subject: [PATCH 33/62] fixed typo for issue 397 thanks to @dirkvdplas Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.4.2.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_4/cis_4.4.2.x.yml b/tasks/section_4/cis_4.4.2.x.yml index 08ef1284..91ba6d3d 100644 --- a/tasks/section_4/cis_4.4.2.x.yml +++ b/tasks/section_4/cis_4.4.2.x.yml @@ -73,7 +73,7 @@ ansible.builtin.shell: | grep -P -- '\bpam_pwquality\.so\b' /etc/pam.d/{password,system}-auth changed_when: false - failed_when: rhel8cis_pwquality_enabled.rc not in [ 0, 1 ] + failed_when: discovered_pwquality_enabled.rc not in [ 0, 1 ] register: discovered_pwquality_enabled - name: "4.4.2.3 | PATCH | Ensure pam_pwquality module is enabled | system-auth" From 81eba789e7574555be76b6d987001aec382e7a88 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 19 Jul 2024 13:27:58 +0100 Subject: [PATCH 34/62] 4.4.2.5 typo fixed Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.4.2.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_4/cis_4.4.2.x.yml b/tasks/section_4/cis_4.4.2.x.yml index 91ba6d3d..2d1850e8 100644 --- a/tasks/section_4/cis_4.4.2.x.yml +++ b/tasks/section_4/cis_4.4.2.x.yml @@ -138,7 +138,7 @@ ansible.builtin.shell: | grep -P -- '\b(pam_unix\.so)\b' /etc/authselect/"$(head -1 /etc/authselect/authselect.conf)"/{system,password}-auth changed_when: false - failed_when: rhel8cis_authselect_pam_unix.rc not in [ 0, 1 ] + failed_when: discovered_authselect_pam_unix.rc not in [ 0, 1 ] register: discovered_authselect_pam_unix - name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled | system-auth" From 4a70e6fddccbe2ec756c93b2002696c36e064845 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 12 Aug 2024 12:39:58 +0100 Subject: [PATCH 35/62] addressed #400 thanks to @dirkvdplas Signed-off-by: Mark Bolwell --- tasks/main.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index c47d8485..bcf1349c 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -139,48 +139,36 @@ - name: Run Section 1 tasks when: - rhel8cis_section1 - tags: - - rhel8cis_section1 ansible.builtin.import_tasks: file: section_1/main.yml - name: Run Section 2 tasks when: - rhel8cis_section2 - tags: - - rhel8cis_section2 ansible.builtin.import_tasks: file: section_2/main.yml - name: Run Section 3 tasks when: - rhel8cis_section3 - tags: - - rhel8cis_section3 ansible.builtin.import_tasks: file: section_3/main.yml - name: Run Section 4 tasks when: - rhel8cis_section4 - tags: - - rhel8cis_section4 ansible.builtin.import_tasks: file: section_4/main.yml - name: run Section 5 tasks when: - rhel8cis_section5 - tags: - - rhel8cis_section5 ansible.builtin.import_tasks: file: section_5/main.yml - name: Run Section 6 tasks when: - rhel8cis_section6 - tags: - - rhel8cis_section6 ansible.builtin.import_tasks: file: section_6/main.yml From 9bf7999f39c67ba2d9e97ae6494c521ec8a40e49 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 12 Aug 2024 17:34:54 +0100 Subject: [PATCH 36/62] Updated authselect section 4.4.2.x new vars #402 Signed-off-by: Mark Bolwell --- defaults/main.yml | 29 +++++-- tasks/main.yml | 23 +++++ tasks/prelim.yml | 44 ---------- tasks/section_4/cis_4.4.2.x.yml | 132 ++++++++++++++--------------- tasks/section_4/cis_4.4.3.1.x.yml | 10 +-- tasks/section_4/cis_4.4.3.2.x.yml | 28 +++--- tasks/section_4/cis_4.4.3.3.x.yml | 10 +-- tasks/section_4/cis_4.4.3.4.x.yml | 12 +-- templates/ansible_vars_goss.yml.j2 | 8 +- 9 files changed, 143 insertions(+), 153 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 9507a83d..1e89f17f 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -686,21 +686,34 @@ rhel8cis_sudolog_location: "/var/log/sudo.log" rhel8cis_sudo_timestamp_timeout: 15 ## PAM -# 4.4.2.x +## 4.4.2.x PAM and Authselect # Do not use authselect if: # Your host is part of Linux Identity Management. # Joining your host to an IdM domain with the ipa-client-install command automatically configures SSSD authentication on your host. # Your host is part of Active Directory via SSSD. # Calling the realm join command to join your host to an Active Directory domain automatically configures SSSD authentication on your host. -rhel8cis_allow_authselect_updates: false +rhel8cis_allow_authselect_updates: true ## rhel8cis_authselect_pkg_update: false # NOTE the risks if system is using SSSD or using ipa-client-install -rhel8cis_authselect_custom_profile_create: false -rhel8cis_authselect_custom_profile_select: false -rhel8cis_authselect: - custom_profile_name: 'cis_example_profile' - default_file_to_copy: "sssd --symlink-meta" - options: with-sudo with-faillock without-nullok with-pwhistory + +## PAM AND Authselect + +# To create a new profile (best for greenfield fresh sites not configured) +# This allows creation of a custom profile using an existing one to build from +# will only create if profiel does not already exist +## options true or false +rhel8cis_authselect_custom_profile_create: true +## Controls: +# - 4.4.2.1 - Ensure custom authselect profile is used +# Settings in place now will fail, they are placeholders from the control example. Due to the way many multiple +# options and ways to configure this control needs to be enabled and settings adjusted to minimise risk. + +# This variable configures the name of the custom profile to be created and selected. +# To be changed from default - cis_example_profile +rhel8cis_authselect_custom_profile_name: cis_example_profile +# Name of the existing authselect profile to copy - options can be found with +# ```authselect list``` on the host to be configured +rhel8cis_authselect_default_profile_to_copy: "sssd --symlink-meta" rhel8cis_pam_faillock: attempts: 5 diff --git a/tasks/main.yml b/tasks/main.yml index bcf1349c..92aa293d 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -108,6 +108,29 @@ vars: sudo_password_rule: rhel8cis_rule_4_3_4 # pragma: allowlist secret +- name: "PRELIM | AUDIT | Check authselect profile is selected" + when: + - rhel8cis_allow_authselect_updates + tags: + - always + block: + - name: "PRELIM | AUDIT | Check authselect profile name has been updated" + ansible.builtin.assert: + that: rhel8cis_authselect_custom_profile_name != 'cis_example_profile' + fail_msg: "You still have the default name for your authselect profile" + + - name: "PRELIM | AUDIT | Check authselect profile is selected" + ansible.builtin.shell: authselect current | head -1 | awk '{print $NF}' + changed_when: false + failed_when: prelim_authselect_current_profile.rc not in [ 0, 1 ] + register: prelim_authselect_current_profile + + - name: "PRELIM | AUDIT | Check authselect profile is selected" + ansible.builtin.assert: + that: prelim_authselect_current_profile is defined + success_msg: "Authselect is running and profile is selected" + fail_msg: Authselect updates have been selected there are issues with profile selection" + - name: Include prelim tasks tags: - prelim_tasks diff --git a/tasks/prelim.yml b/tasks/prelim.yml index d35cf848..ce6962ff 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -228,50 +228,6 @@ ansible.builtin.import_tasks: file: warning_facts.yml -- name: "PRELIM | AUDIT | Check authselect profile is selected" - when: - - rhel8cis_allow_authselect_updates - - rhel8cis_rule_4_4_2_1 or - rhel8cis_rule_4_4_2_2 or - rhel8cis_rule_4_4_2_3 or - rhel8cis_rule_4_4_2_4 or - rhel8cis_rule_4_4_2_5 or - rhel8cis_rule_4_4_3_1_1 or - rhel8cis_rule_4_4_3_1_2 or - rhel8cis_rule_4_4_3_1_3 - tags: - - always - block: - - name: "PRELIM | AUDIT | Check authselect profile name has been updated" - ansible.builtin.assert: - that: rhel8cis_authselect['custom_profile_name'] != 'cis_example_profile' - fail_msg: "You still have the default name for your authselect profile" - - - name: "PRELIM | AUDIT | Check authselect profile is selected" - when: not rhel8cis_authselect_custom_profile_create - ansible.builtin.shell: authselect current - changed_when: false - failed_when: discovered_authselect_running_config.rc not in [ 0, 1 ] - register: discovered_authselect_running_config - - - name: "PRELIM | AUDIT | Check authselect profile is selected" - ansible.builtin.assert: - that: not rhel8cis_authselect_custom_profile_create and "'example' not in rhel8cis_authselect['custom_profile_name']" or discovered_authselect_running_config is defined - success_msg: "Authselect is running and profile is selected" - fail_msg: Authselect updates have been selected there are issues with profile selection" - - - name: "PRELIM | AUDIT | Check profile exists if not created" - ansible.builtin.stat: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}" - register: discovered_authselect_profile - - - name: "PRELIM | AUDIT | Check authselect profile exists if not created" - when: discovered_authselect_profile.stat.exists - ansible.builtin.assert: - that: not rhel8cis_authselect_custom_profile_create - success_msg: "Authselect is running and profile is selected" - fail_msg: Authselect updates have been selected but you have stated create and profile already exists" - - name: "PRELIM | AUDIT | Interactive User accounts home directories" tags: - always diff --git a/tasks/section_4/cis_4.4.2.x.yml b/tasks/section_4/cis_4.4.2.x.yml index 2d1850e8..34d5bb58 100644 --- a/tasks/section_4/cis_4.4.2.x.yml +++ b/tasks/section_4/cis_4.4.2.x.yml @@ -3,9 +3,8 @@ - name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used" when: - rhel8cis_rule_4_4_2_1 - - authselect_version == "OK" - - pam_version == "OK" - rhel8cis_disruption_high + - rhel8cis_allow_authselect_updates tags: - level1-server - level1-workstation @@ -16,22 +15,35 @@ block: - name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used | Create custom profiles" when: - - rhel8cis_authselect_custom_profile_create - - discovered_authselect_running_config.stdout is not defined - - not discovered_authselect_profile.stat.exists - ansible.builtin.shell: "/usr/bin/authselect create-profile {{ rhel8cis_authselect['custom_profile_name'] }} -b {{ rhel8cis_authselect['default_file_to_copy'] }}" + - rhel8cis_authselect_custom_profile_name not in prelim_authselect_current_profile.stdout or + prelim_authselect_current_profile.stdout is not defined + ansible.builtin.shell: "/usr/bin/authselect create-profile {{ rhel8cis_authselect_custom_profile_name }} -b {{ rhel8cis_authselect_default_profile_to_copy }}" args: - creates: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}" + creates: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}" - - name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used | Select profiles" - when: - - rhel8cis_authselect_custom_profile_select - - (discovered_authselect_running_config.stdout is defined and "rhel8cis_authselect['custom_profile_name'] not in discovered_authselect_running_config.stdout") - ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel8cis_authselect['custom_profile_name'] }}{% if rhel8cis_rule_4_4_2_2 %} with-faillock{% endif %}{% if rhel8cis_rule_4_4_2_4 %} with-pwhistory{% endif %}{% if rhel8cis_rule_4_4_3_4_1 %} without-nullok{% endif %} --force" + - name: "4.4.2.1 | AUDIT | Ensure custom authselect profile is used | get profile features" + ansible.builtin.shell: "/usr/bin/authselect list-features custom/{{ rhel8cis_authselect_custom_profile_name }}" + changed_when: false + register: discovered_authselect_profile_features + + - name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used | Add missing pam modules to config | pwquality" + when: "'with-pwquality' not in discovered_authselect_profile_features.stdout_lines" + ansible.builtin.lineinfile: + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^password\s*requisite\s*pam_pwquality.so.* + line: password requisite pam_pwquality.so local_users_only {include if "with-pwquality"} + loop: + - system + - password + + - name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used | Backup and Add pam modules" + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel8cis_authselect_custom_profile_name }}{% if rhel8cis_rule_4_4_2_2 %} with-faillock{% endif %}{% if rhel8cis_rule_4_4_2_3 %} with-pwquality{% endif %}{% if rhel8cis_rule_4_4_2_4 %} with-pwhistory{% endif %}{% if rhel8cis_rule_4_4_3_4_1 %} without-nullok{% endif %} --force --backup=rhel8cis-preremediate-{{ lookup('pipe', 'date +%Y-%m-%d-%H%M') }}" - name: "4.4.2.2 | PATCH | Ensure pam_faillock module is enabled" when: - rhel8cis_rule_4_4_2_2 + - rhel8cis_disruption_high + - rhel8cis_allow_authselect_updates tags: - level1-server - level1-workstation @@ -44,21 +56,23 @@ - NIST800-53R5_IA-5 - authselect - rule_4.4.2.2 - notify: Update_authselect + notify: Authselect update block: - name: "4.4.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config" ansible.builtin.shell: authselect current | grep faillock changed_when: false - failed_when: discovered_authselect_current.rc not in [ 0, 1 ] - register: discovered_authselect_current + failed_when: rhel8cis_authselect_current_faillock.rc not in [ 0, 1 ] + register: rhel8cis_authselect_current_faillock - name: "4.4.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" - when: discovered_authselect_current.rc != 0 - ansible.builtin.shell: "authselect enable-feature with-faillock" + when: rhel8cis_authselect_current_faillock.rc != 0 + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel8cis_authselect_custom_profile_name }}{% if rhel8cis_rule_4_4_2_2 %} with-faillock{% endif %}{% if rhel8cis_rule_4_4_2_3 %} with-pwquality{% endif %}{% if rhel8cis_rule_4_4_2_4 %} with-pwhistory{% endif %}{% if rhel8cis_rule_4_4_3_4_1 %} without-nullok{% endif %}" - name: "4.4.2.3 | PATCH | Ensure pam_pwquality module is enabled" when: - rhel8cis_rule_4_4_2_3 + - rhel8cis_disruption_high + - rhel8cis_allow_authselect_updates tags: - level1-server - level1-workstation @@ -67,41 +81,23 @@ - NIST800-53R5_IA-5 - authselect - rule_4.4.2.3 - notify: Update_authselect block: - - name: "4.4.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Capture current state" - ansible.builtin.shell: | - grep -P -- '\bpam_pwquality\.so\b' /etc/pam.d/{password,system}-auth + - name: "4.4.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Get current config" + ansible.builtin.shell: authselect current | grep quality changed_when: false - failed_when: discovered_pwquality_enabled.rc not in [ 0, 1 ] - register: discovered_pwquality_enabled - - - name: "4.4.2.3 | PATCH | Ensure pam_pwquality module is enabled | system-auth" - when: "'system-auth:password' not in discovered_pwquality_enabled.stdout" - ansible.builtin.lineinfile: - backrefs: true - insertbefore: "{{ item.before | default (omit) }}" - line: "{{ item.line }}" - path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/system-auth - regexp: "{{ item.regexp }}" - loop: - - { regexp: '^(password\s+)(required|requisite|sufficient)(\s+pam_pwquality.so.*)(.*)', line: '\1requisite\3\4', before: '^password\s+[default=1 ignore=ignore success=ok]' } + failed_when: rhel8cis_authselect_current_quality.rc not in [ 0, 1 ] + register: rhel8cis_authselect_current_quality - - name: "4.4.2.3 | PATCH | Ensure pam_pwquality module is enabled | password-auth" - when: "'password-auth:password' not in discovered_pwquality_enabled.stdout" - ansible.builtin.lineinfile: - backrefs: true - insertafter: "{{ item.after | default (omit) }}" - insertbefore: "{{ item.before | default (omit) }}" - line: "{{ item.line }}" - path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/password-auth - regexp: "{{ item.regexp }}" - loop: - - { regexp: '^(password\s+)(required|requisite|sufficient)(\s+pam_pwquality.so.*)(.*)', line: '\1requisite\3\4', before: '^password\s+[default=1 ignore=ignore success=ok]' } + - name: "4.4.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Add feature if missing" + when: rhel8cis_authselect_current_quality.rc != 0 + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel8cis_authselect_custom_profile_name }}{% if rhel8cis_rule_4_4_2_2 %} with-faillock{% endif %}{% if rhel8cis_rule_4_4_2_3 %} with-pwquality{% endif %}{% if rhel8cis_rule_4_4_2_4 %} with-pwhistory{% endif %}{% if rhel8cis_rule_4_4_3_4_1 %} without-nullok{% endif %}" + notify: Authselect update - name: "4.4.2.4 | PATCH | Ensure pam_pwhistory module is enabled" when: - rhel8cis_rule_4_4_2_4 + - rhel8cis_disruption_high + - rhel8cis_allow_authselect_updates tags: - level1-server - level1-workstation @@ -110,21 +106,23 @@ - NIST800-53R5_IA-5 - authselect - rule_4.4.2.4 - notify: Update_authselect block: - name: "4.4.2.4 | AUDIT | Ensure pam_pwhistory module is enabled | Get current config" ansible.builtin.shell: authselect current | grep pwhistory changed_when: false - failed_when: discovered_authselect_current.rc not in [ 0, 1 ] - register: discovered_authselect_current + failed_when: rhel8cis_authselect_current_history.rc not in [ 0, 1 ] + register: rhel8cis_authselect_current_history - name: "4.4.2.4 | PATCH | Ensure pam_pwhistory module is enabled | enable feature" - when: discovered_authselect_current.rc != 0 - ansible.builtin.shell: "authselect enable-feature with-pwhistory" + when: rhel8cis_authselect_current_history.rc != 0 + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel8cis_authselect_custom_profile_name }}{% if rhel8cis_rule_4_4_2_2 %} with-faillock{% endif %}{% if rhel8cis_rule_4_4_2_3 %} with-pwquality{% endif %}{% if rhel8cis_rule_4_4_2_4 %} with-pwhistory{% endif %}{% if rhel8cis_rule_4_4_3_4_1 %} without-nullok{% endif %}" + notify: Authselect update - name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled" when: - rhel8cis_rule_4_4_2_5 + - rhel8cis_disruption_high + - rhel8cis_allow_authselect_updates tags: - level1-server - level1-workstation @@ -138,31 +136,33 @@ ansible.builtin.shell: | grep -P -- '\b(pam_unix\.so)\b' /etc/authselect/"$(head -1 /etc/authselect/authselect.conf)"/{system,password}-auth changed_when: false - failed_when: discovered_authselect_pam_unix.rc not in [ 0, 1 ] - register: discovered_authselect_pam_unix + failed_when: rhel8cis_authselect_pam_unix.rc not in [ 0, 1 ] + register: rhel8cis_authselect_pam_unix - name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled | system-auth" - when: "'system-auth:password' not in discovered_authselect_pam_unix.stdout" + when: "'system-auth:password' not in rhel8cis_authselect_pam_unix.stdout" ansible.builtin.lineinfile: + path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/system-auth + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" backrefs: true insertafter: "{{ item.after | default (omit) }}" insertbefore: "{{ item.before | default (omit) }}" - line: "{{ item.line }}" - path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/system-auth - regexp: "{{ item.regexp }}" - loop: - - { regexp: '^(auth\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', after: '^auth.*pam_faillock.*preauth' } - - { regexp: '^(password\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', before: '^password.*pam_deny.so' } + loop: + - { regexp: '^(auth\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', after: '^auth.*pam_faillock.*preauth' } + - { regexp: '^(password\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', before: '^password.*pam_deny.so' } + notify: Authselect update - name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled | password-auth" - when: "'password-auth:password' not in discovered_authselect_pam_unix.stdout" + when: "'password-auth:password' not in rhel8cis_authselect_pam_unix.stdout" ansible.builtin.lineinfile: + path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/password-auth + line: "{{ item.line }}" + regexp: "{{ item.regexp }}" backrefs: true insertafter: "{{ item.after | default (omit) }}" insertbefore: "{{ item.before | default (omit) }}" - line: "{{ item.line }}" - path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/password-auth - regexp: "{{ item.regexp }}" - loop: - - { regexp: '^(auth\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\2', after: '^auth.*pam_faillock.*preauth' } - - { regexp: '^(password\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', before: '^password.*pam_deny.so' } + loop: + - { regexp: '^(auth\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\2', after: '^auth.*pam_faillock.*preauth' } + - { regexp: '^(password\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', before: '^password.*pam_deny.so' } + notify: Authselect update diff --git a/tasks/section_4/cis_4.4.3.1.x.yml b/tasks/section_4/cis_4.4.3.1.x.yml index 062efcee..13d39acd 100644 --- a/tasks/section_4/cis_4.4.3.1.x.yml +++ b/tasks/section_4/cis_4.4.3.1.x.yml @@ -41,7 +41,7 @@ - rhel8cis_allow_authselect_updates - discovered_authselect_current.rc != 0 ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+deny\s*=\s*\S+(.*$) replace: \1\2\3 loop: @@ -79,10 +79,10 @@ - name: "4.4.3.1.2 | PATCH | Ensure password unlock time is configured | authselect_files" when: - rhel8cis_allow_authselect_updates - - "'example' not in rhel8cis_authselect['custom_profile_name']" + - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+unlock_time\s*=\s*\S+(.*$) replace: \1\2\3 loop: @@ -120,10 +120,10 @@ - name: "4.4.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | authselect_files" when: - rhel8cis_allow_authselect_updates - - "'example' not in rhel8cis_authselect['custom_profile_name']" + - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s"{{ rhel8cis_pam_faillock['root_option'] }}"(\s*=\s*\d|.*)\S+(.*$) replace: \1\2\3\4 loop: diff --git a/tasks/section_4/cis_4.4.3.2.x.yml b/tasks/section_4/cis_4.4.3.2.x.yml index c3f8e1fd..e9c035f8 100644 --- a/tasks/section_4/cis_4.4.3.2.x.yml +++ b/tasks/section_4/cis_4.4.3.2.x.yml @@ -32,10 +32,10 @@ - name: "4.4.3.2.1 | PATCH | Ensure password number of changed characters is configured | authselect_files" when: - rhel8cis_allow_authselect_updates - - "'example' not in rhel8cis_authselect['custom_profile_name']" + - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+difok\s*=\s*\S+(.*$) replace: \1\2\3 loop: @@ -74,10 +74,10 @@ - name: "4.4.3.2.2 | PATCH | Ensure password length is configured | authselect_files" when: - rhel8cis_allow_authselect_updates - - "'example' not in rhel8cis_authselect['custom_profile_name']" + - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+minlen\s*=\s*\S+(.*$) replace: \1\2\3 loop: @@ -116,10 +116,10 @@ - name: "4.4.3.2.3 | PATCH | Ensure password complexity is configured | authselect_files" when: - rhel8cis_allow_authselect_updates - - "'example' not in rhel8cis_authselect['custom_profile_name']" + - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+minclass\s*=\s*\S+(.*$) replace: \1\2\3 loop: @@ -158,10 +158,10 @@ - name: "4.4.3.2.4 | PATCH | Ensure password same consecutive characters is configured | authselect_files" when: - rhel8cis_allow_authselect_updates - - "'example' not in rhel8cis_authselect['custom_profile_name']" + - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxrepeat\s*=\s*\S+(.*$) replace: \1\2\3 loop: @@ -200,10 +200,10 @@ - name: "4.4.3.2.5 | PATCH | Ensure password same consecutive characters is configured | authselect_files" when: - rhel8cis_allow_authselect_updates - - "'example' not in rhel8cis_authselect['custom_profile_name']" + - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxseq\s*=\s*\S+(.*$) replace: \1\2\3 loop: @@ -242,10 +242,10 @@ - name: "4.4.3.2.6 | PATCH | Ensure password dictionary check is enabled | authselect_files" when: - rhel8cis_allow_authselect_updates - - "'example' not in rhel8cis_authselect['custom_profile_name']" + - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+dictcheck\s*=\s*\S+(.*$) replace: \1\2\3 loop: @@ -284,10 +284,10 @@ - name: "4.4.3.2.7 | PATCH | Ensure password dictionary check is enabled | authselect_files" when: - rhel8cis_allow_authselect_updates - - "'example' not in rhel8cis_authselect['custom_profile_name']" + - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+enforce_for_root(.*$) replace: \1\2\3 loop: diff --git a/tasks/section_4/cis_4.4.3.3.x.yml b/tasks/section_4/cis_4.4.3.3.x.yml index b321e3e1..cf0321d2 100644 --- a/tasks/section_4/cis_4.4.3.3.x.yml +++ b/tasks/section_4/cis_4.4.3.3.x.yml @@ -22,10 +22,10 @@ - name: "4.4.3.3.1 | PATCH | Ensure password number of changed characters is configured | authselect_files" when: - rhel8cis_allow_authselect_updates - - "'example' not in rhel8cis_authselect['custom_profile_name']" + - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\s+remember\s*=\s*\S+(.*$) replace: \1\2\3 loop: @@ -64,10 +64,10 @@ - name: "4.4.3.3.2 | PATCH | Ensure password history is enforced for the root user | authselect_files" when: - rhel8cis_allow_authselect_updates - - "'example' not in rhel8cis_authselect['custom_profile_name']" + - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\s+enforce_for_root(.*$) replace: \1\2\3 loop: @@ -107,7 +107,7 @@ notify: Update_authselect community.general.pamd: name: "{{ item }}-auth" - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}" type: password control: requisite module_path: pam_pwhistory.so diff --git a/tasks/section_4/cis_4.4.3.4.x.yml b/tasks/section_4/cis_4.4.3.4.x.yml index 87dbcc0e..f6c1be0a 100644 --- a/tasks/section_4/cis_4.4.3.4.x.yml +++ b/tasks/section_4/cis_4.4.3.4.x.yml @@ -73,10 +73,10 @@ - discovered_pam_remember is defined - discovered_pam_remember | length > 0 - rhel8cis_allow_authselect_updates - - "'example' not in rhel8cis_authselect['custom_profile_name']" + - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)remember\s*=\s*\d+(.*$) replace: \1\2\3 loop: @@ -118,10 +118,10 @@ - discovered_hash_state is defined - discovered_hash_state | length > 0 - rhel8cis_allow_authselect_updates - - "'example' not in rhel8cis_authselect['custom_profile_name']" + - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)(sha512|yescrypt)\s*=\s*\d+(.*$) replace: \1\2\4 {{ rhel8cis_pam_pwhash }} loop: @@ -163,10 +163,10 @@ - discovered_pam_authtok is defined - discovered_pam_authtok | length > 0 - rhel8cis_allow_authselect_updates - - "'example' not in rhel8cis_authselect['custom_profile_name']" + - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)\s+use_authtok(.*$) replace: \1\3\4 use_authtok loop: diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index 04a487bc..5171aa3d 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -619,11 +619,9 @@ rhel8cis_sudo_timestamp_timeout: {{ rhel8cis_sudo_timestamp_timeout }} rhel8cis_authselect_pkg_update: {{ rhel8cis_authselect_pkg_update }} # NOTE the risks if system is using SSSD or using ipa-client-install rhel8cis_allow_authselect_updates: {{ rhel8cis_allow_authselect_updates }} rhel8cis_authselect_custom_profile_create: {{ rhel8cis_authselect_custom_profile_create }} -rhel8cis_authselect_custom_profile_select: {{ rhel8cis_authselect_custom_profile_select }} -rhel8cis_authselect: - custom_profile_name: '{{ rhel8cis_authselect.custom_profile_name }}' - default_file_to_copy: "{{ rhel8cis_authselect.default_file_to_copy }}" - options: {{ rhel8cis_authselect }} +rhel8cis_authselect_custom_profile_name: '{{ rhel8cis_authselect_custom_profile_name }}' +rhel8cis_authselect_default_file_to_copy: "{{ rhel8cis_authselect_default_file_to_copy }}" +rhel8cis_authselect_options: {{ rhel8cis_authselect_options }} rhel8cis_pam_faillock: attempts: {{ rhel8cis_pam_faillock.attempts }} From 48f959eef9bd5fc38da88c4b1e21c8720a23e4b9 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 12 Aug 2024 17:35:23 +0100 Subject: [PATCH 37/62] fix typo Signed-off-by: Mark Bolwell --- tasks/post_remediation_audit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index ea72759c..b3c18234 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -35,7 +35,7 @@ - audit_format == "documentation" block: - name: Post Audit | Capture audit data if documentation format - ansible.builtin.shell: "tail -2 /opt/audit_ubuntu2204-CIS-UBUNTU22_1720624848.documentation" + ansible.builtin.shell: "tail -2 {{ post_audit_outfile }}" register: post_audit_summary changed_when: false From da0163e0b9f0ebc2d17ef83d788fae54682127f6 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 12 Aug 2024 21:41:52 +0100 Subject: [PATCH 38/62] Added space Signed-off-by: Mark Bolwell --- vars/audit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vars/audit.yml b/vars/audit.yml index 9dc666a6..4de8a7dd 100644 --- a/vars/audit.yml +++ b/vars/audit.yml @@ -34,7 +34,7 @@ audit_format: json audit_vars_path: "{{ audit_conf_dir }}/vars/{{ ansible_facts.hostname }}.yml" audit_results: | - The{% if not audit_only %} pre remediation{% endif %} audit results are: {{ pre_audit_results}} + The{% if not audit_only %} pre remediation{% endif %} audit results are: {{ pre_audit_results }} {% if not audit_only %}The post remediation audit results are: {{ post_audit_results }}{% endif %} Full breakdown can be found in {{ audit_log_dir }} From 44be328941c3f285814cb1fb8b72392941fb9ca6 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 13 Aug 2024 08:26:54 +0100 Subject: [PATCH 39/62] updated to enable arm64 support Signed-off-by: Mark Bolwell --- tasks/LE_audit_setup.yml | 2 +- vars/audit.yml | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index 70674142..1b5ba8a9 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -8,7 +8,7 @@ audit_pkg_arch_name: AMD64 - name: Pre Audit Setup | Set audit package name | ARM64 - when: ansible_facts.machine == "arm64" + when: ansible_facts.machine == "aarch64" ansible.builtin.set_fact: audit_pkg_arch_name: ARM64 diff --git a/vars/audit.yml b/vars/audit.yml index 4de8a7dd..7a2e9ec8 100644 --- a/vars/audit.yml +++ b/vars/audit.yml @@ -26,8 +26,9 @@ post_audit_outfile: "{{ audit_log_dir }}/{{ ansible_facts.hostname }}-{{ benchma ### Audit binary settings ### audit_bin_version: - release: v0.4.4 - AMD64_checksum: 'sha256:1c4f54b22fde9d4d5687939abc2606b0660a5d14a98afcd09b04b793d69acdc5' + release: v0.4.8 + AMD64_checksum: 'sha256:85d00b7bba5f175bec95de7dfe1f71f8f25204914aad4c6f03c8457868eb6e2f' + ARM64_checksum: 'sha256:bca8c898bfd35b94c51455ece6193c95e2cd7b2b183ac2047b2d76291e73e47d' audit_bin_path: /usr/local/bin/ audit_bin: "{{ audit_bin_path }}goss" audit_format: json From 74e869c2b0e103c9bd280051ee8d2eacb6032100 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 13 Aug 2024 11:39:32 +0100 Subject: [PATCH 40/62] updated Signed-off-by: Mark Bolwell --- Changelog.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Changelog.md b/Changelog.md index b1e5a0c9..8a8fb852 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,16 @@ # Changes to rhel8CIS +## Benchmark v3.0.0 + +### 2.1 updates August 2024 + +new workflow +audit updates +authselect rewrite +thanks to @msachikanta, @fgierlinger, @bantify, @txdavec, @csabapatyi@dirkvdplas, @karlg100 and @devallan for issues and fixes +now able to run audit on ARM64 although not officially supported by CIS feedback needed +audit binary update to 0.4.8 + ## 2.0 based on CIS 3.0.0 ### This is not an upgrade for CIS v2.0.0 due to the number of changes treat as a new baseline From 9e007d3969df2000517f2bd79d5e5735d607d884 Mon Sep 17 00:00:00 2001 From: Dan D Date: Tue, 13 Aug 2024 12:29:33 -0700 Subject: [PATCH 41/62] changed maxseq to maxsequence to correct the syntax Signed-off-by: Dan D --- tasks/section_4/cis_4.4.3.2.x.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasks/section_4/cis_4.4.3.2.x.yml b/tasks/section_4/cis_4.4.3.2.x.yml index c3f8e1fd..68c3fb07 100644 --- a/tasks/section_4/cis_4.4.3.2.x.yml +++ b/tasks/section_4/cis_4.4.3.2.x.yml @@ -184,14 +184,14 @@ ansible.builtin.lineinfile: path: /etc/security/pwquality.conf state: present - regexp: '^(#|)\s*maxseq\s*=\s*\d' - line: "maxseq = {{ rhel8cis_pam_pwquality['maxseq'] }}" + regexp: '^(#|)\s*maxsequence\s*=\s*\d' + line: "maxsequence = {{ rhel8cis_pam_pwquality['maxseq'] }}" - name: "4.4.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | pam_files" when: not rhel8cis_allow_authselect_updates ansible.builtin.replace: path: "/etc/pam.d/{{ item }}-auth" - regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxseq\s*=\s*\S+(.*$) + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxsequence\s*=\s*\S+(.*$) replace: \1\2\3 loop: - password @@ -204,7 +204,7 @@ notify: Update_authselect ansible.builtin.replace: path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" - regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxseq\s*=\s*\S+(.*$) + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxsequence\s*=\s*\S+(.*$) replace: \1\2\3 loop: - password From f0db4e558d94d47f922a67d4fd539f20ad674b80 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 22 Aug 2024 08:56:38 +0100 Subject: [PATCH 42/62] removed pamd for lineinfile Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.4.3.3.x.yml | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/tasks/section_4/cis_4.4.3.3.x.yml b/tasks/section_4/cis_4.4.3.3.x.yml index cf0321d2..183d36d6 100644 --- a/tasks/section_4/cis_4.4.3.3.x.yml +++ b/tasks/section_4/cis_4.4.3.3.x.yml @@ -104,15 +104,12 @@ when: - rhel8cis_allow_authselect_updates - discovered_pwhistory_authtok.rc != 0 - notify: Update_authselect - community.general.pamd: - name: "{{ item }}-auth" - path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}" - type: password - control: requisite - module_path: pam_pwhistory.so - module_arguments: 'use_authtok' - state: updated + ansible.builtin.lineinfile: + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+)(requisite|required|sufficient)(\s+pam_unix.so\s)(.*)use_authtok(.*$) + line: \1\2\3\4use_authtok\5 + backrefs: true loop: - password - system + notify: Update_authselect From 21016769fda340887a7fc9c098d4620da38b586d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 22 Aug 2024 09:38:39 +0100 Subject: [PATCH 43/62] updated Signed-off-by: Mark Bolwell --- templates/ansible_vars_goss.yml.j2 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index 5171aa3d..7b3eeeb4 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -616,12 +616,8 @@ rhel8cis_sudo_timestamp_timeout: {{ rhel8cis_sudo_timestamp_timeout }} ## PAM # 4.4.2.x -rhel8cis_authselect_pkg_update: {{ rhel8cis_authselect_pkg_update }} # NOTE the risks if system is using SSSD or using ipa-client-install rhel8cis_allow_authselect_updates: {{ rhel8cis_allow_authselect_updates }} -rhel8cis_authselect_custom_profile_create: {{ rhel8cis_authselect_custom_profile_create }} rhel8cis_authselect_custom_profile_name: '{{ rhel8cis_authselect_custom_profile_name }}' -rhel8cis_authselect_default_file_to_copy: "{{ rhel8cis_authselect_default_file_to_copy }}" -rhel8cis_authselect_options: {{ rhel8cis_authselect_options }} rhel8cis_pam_faillock: attempts: {{ rhel8cis_pam_faillock.attempts }} From ad05f46c3186cd3a2b7d2fb355294382f3f3a01f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 22 Aug 2024 09:48:29 +0100 Subject: [PATCH 44/62] fix typo in control Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.4.3.2.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_4/cis_4.4.3.2.x.yml b/tasks/section_4/cis_4.4.3.2.x.yml index 163f8741..8538d1f3 100644 --- a/tasks/section_4/cis_4.4.3.2.x.yml +++ b/tasks/section_4/cis_4.4.3.2.x.yml @@ -203,7 +203,7 @@ - "'example' not in rhel8cis_authselect_custom_profile_name" notify: Update_authselect ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxsequence\s*=\s*\S+(.*$) replace: \1\2\3 loop: From 20ddcb325400246b7792c6b45891310171fba2cf Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 22 Aug 2024 13:22:27 +0100 Subject: [PATCH 45/62] fixed error for remember value Signed-off-by: Mark Bolwell --- templates/ansible_vars_goss.yml.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index 7b3eeeb4..9284799b 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -636,7 +636,7 @@ rhel8cis_pam_pwquality: minclass: {{ rhel8cis_pam_pwquality.minclass }} rhel8cis_pam_pwhistory: - remember: {{ rhel8cis_pam_pwhistory }} + remember: {{ rhel8cis_pam_pwhistory.remember }} rhel8cis_pam_pwhash: {{ rhel8cis_pam_pwhash }} From 0e86c3444eaf3b53cd133cac59d13c4a9f62d7f3 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 22 Aug 2024 13:23:16 +0100 Subject: [PATCH 46/62] updated to acceoted values Signed-off-by: Mark Bolwell --- defaults/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 1e89f17f..66d8ba6c 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -563,7 +563,7 @@ rhel8cis_ntp_server_options: "iburst" # mask - if a dependancy for product so cannot be removed # Server Services rhel8cis_autofs_services: false -rhel8cis_autofs_mask: true +rhel8cis_autofs_mask: false rhel8cis_avahi_server: false rhel8cis_avahi_mask: false rhel8cis_dhcp_server: false @@ -800,7 +800,7 @@ rhel8cis_auditd: disk_full_action: halt action_mail_acct: root space_left_action: email - admin_space_left_action: email + admin_space_left_action: single max_log_file_action: keep_logs # This can be used to configure other keys in auditd.conf From 938013c67067cbf6f5931f45a25543211967f077 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 22 Aug 2024 13:44:34 +0100 Subject: [PATCH 47/62] fix typo Signed-off-by: Mark Bolwell --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 8a8fb852..e089b3d4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,7 +7,7 @@ new workflow audit updates authselect rewrite -thanks to @msachikanta, @fgierlinger, @bantify, @txdavec, @csabapatyi@dirkvdplas, @karlg100 and @devallan for issues and fixes +thanks to @msachikanta, @fgierlinger, @bantify, @txdavec, @csabapatyi @dirkvdplas, @karlg100 and @devallan for issues and fixes now able to run audit on ARM64 although not officially supported by CIS feedback needed audit binary update to 0.4.8 From 9a9cdb6ecf185b7298fbc66bfbd6c500a5dc6a97 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 13 Sep 2024 11:00:34 +0100 Subject: [PATCH 48/62] Thanks to @draygoX #407 Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.4.3.4.x.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasks/section_4/cis_4.4.3.4.x.yml b/tasks/section_4/cis_4.4.3.4.x.yml index f6c1be0a..9c5cecf7 100644 --- a/tasks/section_4/cis_4.4.3.4.x.yml +++ b/tasks/section_4/cis_4.4.3.4.x.yml @@ -63,7 +63,7 @@ ansible.builtin.replace: path: "/etc/pam.d/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)remember\s*=\s*\d+(.*$) - replace: \1\2\3 + replace: \1\3\4 loop: - password - system @@ -78,7 +78,7 @@ ansible.builtin.replace: path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)remember\s*=\s*\d+(.*$) - replace: \1\2\3 + replace: \1\3\4 loop: - password - system @@ -108,7 +108,7 @@ ansible.builtin.replace: path: "/etc/pam.d/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)(sha512|yescrypt)(.*$) - replace: \1\2\4 {{ rhel8cis_pam_pwhash }} + replace: \1\3\5 {{ rhel8cis_pam_pwhash }} loop: - password - system @@ -123,7 +123,7 @@ ansible.builtin.replace: path: "/etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)(sha512|yescrypt)\s*=\s*\d+(.*$) - replace: \1\2\4 {{ rhel8cis_pam_pwhash }} + replace: \1\3\5 {{ rhel8cis_pam_pwhash }} loop: - password - system From f9d58c7351130ea2ab8df51469f1f58b5c3db51f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Sep 2024 08:59:06 +0100 Subject: [PATCH 49/62] fix typo Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index ce6962ff..56d4d49e 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -291,7 +291,7 @@ - rhel8cis_rule_6_2_8 tags: - always - ansible.builtin.shell: "cat /etc/passwd | awk -F: '($3 == 0 && $1 != \"root\") {i++;print $1 } END {exit i}'" + ansible.builtin.shell: "cat /etc/passwd | awk -F: '($3 == 0 && $1 != \"root\") {i++;print $1 } END {exit 1}'" changed_when: false check_mode: false register: discovered_uid_zero_accounts_except_root From 9b76c39cda7249387c6e6c45892282c8d9e8ca7d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Sep 2024 11:11:13 +0100 Subject: [PATCH 50/62] Updated logixc for uid zero 6.2.9 Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 56d4d49e..df3b5e64 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -288,10 +288,11 @@ - name: "PRELIM | AUDIT | Gather UID 0 accounts other than root" when: - - rhel8cis_rule_6_2_8 + - rhel8cis_rule_6_2_9 tags: - always ansible.builtin.shell: "cat /etc/passwd | awk -F: '($3 == 0 && $1 != \"root\") {i++;print $1 } END {exit 1}'" + failed_when: discovered_uid_zero_accounts_except_root.rc not in [ 0, 1 ] changed_when: false check_mode: false register: discovered_uid_zero_accounts_except_root From d12a8fff5dce4c57ac074252877b19824ed14498 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 17:48:44 +0000 Subject: [PATCH 51/62] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.18.4 → v8.19.2](https://github.com/gitleaks/gitleaks/compare/v8.18.4...v8.19.2) - [github.com/ansible-community/ansible-lint: v24.7.0 → v24.9.0](https://github.com/ansible-community/ansible-lint/compare/v24.7.0...v24.9.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e3bd1700..32ed0167 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,12 +35,12 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.18.4 + rev: v8.19.2 hooks: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v24.7.0 + rev: v24.9.0 hooks: - id: ansible-lint name: Ansible-lint From 6ac85ba182981ec0851da5efe5fe98b1ff4bf5aa Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 17:49:00 +0000 Subject: [PATCH 52/62] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v24.9.0 → v24.9.2](https://github.com/ansible-community/ansible-lint/compare/v24.9.0...v24.9.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 32ed0167..bcbce980 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,7 @@ repos: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v24.9.0 + rev: v24.9.2 hooks: - id: ansible-lint name: Ansible-lint From f3ebef8978bd6028cfa3f76f2a8a92eefac6f667 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 25 Sep 2024 09:24:41 +0100 Subject: [PATCH 53/62] updated rule 5.1.4 Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.1.4.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tasks/section_5/cis_5.1.4.yml b/tasks/section_5/cis_5.1.4.yml index ef2ee18c..27fbba29 100644 --- a/tasks/section_5/cis_5.1.4.yml +++ b/tasks/section_5/cis_5.1.4.yml @@ -13,7 +13,7 @@ - rule_5.1.4 block: - name: "5.1.4 | AUDIT | Ensure permissions on all logfiles are configured | find files" - ansible.builtin.shell: find /var/log/ -type f -exec ls {} \; + ansible.builtin.shell: find -L /var/log/ -type f -perm /g+wx,o+rwx -exec ls {} \; changed_when: false failed_when: false register: discovered_logfiles @@ -26,13 +26,17 @@ - item != "/var/log/lastlog" ansible.builtin.file: path: "{{ item }}" - mode: u-x,g-wx,o-rwx + mode: 'u-x,g-wx,o-rwx' + failed_when: discovered_logfile_list.state not in '[ file, absent ]' + register: discovered_logfile_list loop: "{{ discovered_logfiles.stdout_lines }}" - name: "5.1.4 | PATCH | Ensure permissions on all logfiles are configured | change permissions" ansible.builtin.file: path: "{{ item.name }}" - mode: ('ug-x,o-wx') + mode: 'ug-x,o-wx' + failed_when: discovered_logfile_list.state not in '[ file, absent ]' + register: discovered_logfile_list with_fileglob: - /var/log/*tmp.*" - /var/log/lastlog" From 82af4437d962372f0a4cfcd37b1855c8b32df63f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 25 Sep 2024 10:05:10 +0100 Subject: [PATCH 54/62] Added quotes to file mode Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.7.x.yml | 12 ++++++------ tasks/section_4/cis_4.1.1.x.yml | 2 +- tasks/section_5/cis_5.2.4.x.yml | 8 ++++---- tasks/section_6/cis_6.1.x.yml | 18 +++++++++--------- tasks/section_6/cis_6.2.x.yml | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tasks/section_1/cis_1.7.x.yml b/tasks/section_1/cis_1.7.x.yml index 9c240b4e..21714e09 100644 --- a/tasks/section_1/cis_1.7.x.yml +++ b/tasks/section_1/cis_1.7.x.yml @@ -18,7 +18,7 @@ dest: /etc/motd owner: root group: root - mode: go-rx + mode: 'go-rx' - name: "1.7.2 | PATCH | Ensure local login warning banner is configured properly" when: @@ -37,7 +37,7 @@ dest: /etc/issue owner: root group: root - mode: go-rx + mode: 'go-rx' - name: "1.7.3 | PATCH | Ensure remote login warning banner is configured properly" when: @@ -57,7 +57,7 @@ dest: /etc/issue.net owner: root group: root - mode: go-wx + mode: 'go-wx' - name: "1.7.4 | PATCH | Ensure access to /etc/motd is configured" when: @@ -76,7 +76,7 @@ state: file owner: root group: root - mode: go-wx + mode: 'go-wx' - name: "1.7.5 | PATCH | Ensure access to /etc/issue is configured" when: @@ -95,7 +95,7 @@ state: file owner: root group: root - mode: go-wx + mode: 'go-wx' - name: "1.7.6 | PATCH | Ensure access to /etc/issue.net is configured" when: @@ -114,4 +114,4 @@ state: file owner: root group: root - mode: go-wx + mode: 'go-wx' diff --git a/tasks/section_4/cis_4.1.1.x.yml b/tasks/section_4/cis_4.1.1.x.yml index b70ee61f..6e2d2464 100644 --- a/tasks/section_4/cis_4.1.1.x.yml +++ b/tasks/section_4/cis_4.1.1.x.yml @@ -161,4 +161,4 @@ state: '{{ "file" if discovered_cron_allow_state.stat.exists else "touch" }}' owner: root group: root - mode: g-wx,o-rwx + mode: 'g-wx,o-rwx' diff --git a/tasks/section_5/cis_5.2.4.x.yml b/tasks/section_5/cis_5.2.4.x.yml index e78a7ff1..2914005e 100644 --- a/tasks/section_5/cis_5.2.4.x.yml +++ b/tasks/section_5/cis_5.2.4.x.yml @@ -12,7 +12,7 @@ ansible.builtin.file: path: "{{ discovered_audit_logfile.stdout | dirname }}" state: directory - mode: g-w,o-rwx + mode: 'g-w,o-rwx' - name: | "5.2.4.2 | PATCH | Ensure audit log files are mode 0640 or less permissive" @@ -43,7 +43,7 @@ "5.2.4.4 | PATCH | Ensure only authorized groups are assigned ownership of audit log files" ansible.builtin.file: path: "{{ discovered_audit_logfile.stdout }}" - mode: "{% if discovered_auditlog_info.stat.mode != '0600' %}0640{% endif %}" + mode: 'o-x,g-wx,o-rwx' owner: root group: root @@ -58,7 +58,7 @@ - rule_5.2.4.5 ansible.builtin.file: path: "{{ item.path }}" - mode: g-wx,o-rwx + mode: 'g-wx,o-rwx' loop: "{{ discovered_auditd_conf_files.files }}" loop_control: label: "{{ item.path }}" @@ -120,7 +120,7 @@ - name: "5.2.4.8 | PATCH | Ensure audit tools are 755 or more restrictive | set if required" ansible.builtin.file: path: "{{ item.item }}" - mode: g-w,o-w + mode: 'g-w,o-w' loop: "{{ discovered_audit_bins_mode.results }}" loop_control: label: "{{ item.item }}" diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 0c16bd2f..d56d60a3 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -16,7 +16,7 @@ path: /etc/passwd owner: root group: root - mode: u-x,go-wx + mode: 'u-x,go-wx' - name: "6.1.2 | PATCH | Ensure permissions on /etc/passwd- are configured" when: @@ -34,7 +34,7 @@ path: /etc/passwd- owner: root group: root - mode: u-x,go-wx + mode: 'u-x,go-wx' - name: "6.1.3 | PATCH | Ensure permissions on /etc/security/opasswd are configured" when: @@ -70,7 +70,7 @@ path: /etc/group owner: root group: root - mode: u-x,go-wx + mode: 'u-x,go-wx' - name: "6.1.5 | PATCH | Ensure permissions on /etc/group- are configured" when: @@ -88,7 +88,7 @@ path: /etc/group- owner: root group: root - mode: u-x,go-wx + mode: 'u-x,go-wx' - name: "6.1.6 | PATCH | Ensure permissions on /etc/shadow are configured" when: @@ -178,7 +178,7 @@ path: /etc/shells owner: root group: root - mode: u-x,go-wx + mode: 'u-x,go-wx' - name: "6.1.11 | PATCH | Ensure world writable files and directories are secured" when: @@ -209,7 +209,7 @@ - rhel8cis_no_world_write_adjust ansible.builtin.file: path: '{{ item }}' - mode: o-w + mode: 'o-w' state: touch with_items: "{{ discovered_perms_results.stdout_lines }}" @@ -252,7 +252,7 @@ ansible.builtin.shell: find {{ item.mount }} -xdev -nogroup -not -fstype nfs changed_when: false failed_when: false - check_mode: false + check_mode: 'false' register: discovered_ungrouped_items with_items: - "{{ ansible_facts.mounts }}" @@ -308,7 +308,7 @@ ansible.builtin.shell: find {{ item.mount }} -xdev -type f -perm -4000 -not -fstype nfs changed_when: false failed_when: false - check_mode: false + check_mode: 'false' register: discovered_suid_executables loop: "{{ ansible_facts.mounts }}" loop_control: @@ -318,7 +318,7 @@ ansible.builtin.shell: find {{ item.mount }} -xdev -type f -perm -2000 -not -fstype nfs changed_when: false failed_when: false - check_mode: false + check_mode: 'false' register: discovered_sgid_executables loop: "{{ ansible_facts.mounts }}" loop_control: diff --git a/tasks/section_6/cis_6.2.x.yml b/tasks/section_6/cis_6.2.x.yml index 24fe621b..befee5f1 100644 --- a/tasks/section_6/cis_6.2.x.yml +++ b/tasks/section_6/cis_6.2.x.yml @@ -417,5 +417,5 @@ ansible.builtin.file: path: '{{ item }}' - mode: go-w + mode: 'go-w' with_items: "{{ discovered_dot_files.stdout_lines }}" From 13240cd0321ef54e2d5dedfe1b2d4c1d90ee689d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 25 Sep 2024 10:17:41 +0100 Subject: [PATCH 55/62] updated register naming Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.4.2.x.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tasks/section_4/cis_4.4.2.x.yml b/tasks/section_4/cis_4.4.2.x.yml index 34d5bb58..d3e572f4 100644 --- a/tasks/section_4/cis_4.4.2.x.yml +++ b/tasks/section_4/cis_4.4.2.x.yml @@ -61,11 +61,11 @@ - name: "4.4.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config" ansible.builtin.shell: authselect current | grep faillock changed_when: false - failed_when: rhel8cis_authselect_current_faillock.rc not in [ 0, 1 ] - register: rhel8cis_authselect_current_faillock + failed_when: discovered_uthselect_current_faillock.rc not in [ 0, 1 ] + register: discovered_authselect_current_faillock - name: "4.4.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" - when: rhel8cis_authselect_current_faillock.rc != 0 + when: discovered_authselect_current_faillock.rc != 0 ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel8cis_authselect_custom_profile_name }}{% if rhel8cis_rule_4_4_2_2 %} with-faillock{% endif %}{% if rhel8cis_rule_4_4_2_3 %} with-pwquality{% endif %}{% if rhel8cis_rule_4_4_2_4 %} with-pwhistory{% endif %}{% if rhel8cis_rule_4_4_3_4_1 %} without-nullok{% endif %}" - name: "4.4.2.3 | PATCH | Ensure pam_pwquality module is enabled" @@ -85,11 +85,11 @@ - name: "4.4.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Get current config" ansible.builtin.shell: authselect current | grep quality changed_when: false - failed_when: rhel8cis_authselect_current_quality.rc not in [ 0, 1 ] - register: rhel8cis_authselect_current_quality + failed_when: discovered_authselect_current_quality.rc not in [ 0, 1 ] + register: discovered_authselect_current_quality - name: "4.4.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Add feature if missing" - when: rhel8cis_authselect_current_quality.rc != 0 + when: discovered_authselect_current_quality.rc != 0 ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel8cis_authselect_custom_profile_name }}{% if rhel8cis_rule_4_4_2_2 %} with-faillock{% endif %}{% if rhel8cis_rule_4_4_2_3 %} with-pwquality{% endif %}{% if rhel8cis_rule_4_4_2_4 %} with-pwhistory{% endif %}{% if rhel8cis_rule_4_4_3_4_1 %} without-nullok{% endif %}" notify: Authselect update @@ -110,11 +110,11 @@ - name: "4.4.2.4 | AUDIT | Ensure pam_pwhistory module is enabled | Get current config" ansible.builtin.shell: authselect current | grep pwhistory changed_when: false - failed_when: rhel8cis_authselect_current_history.rc not in [ 0, 1 ] - register: rhel8cis_authselect_current_history + failed_when: discovered_authselect_current_history.rc not in [ 0, 1 ] + register: discovered_authselect_current_history - name: "4.4.2.4 | PATCH | Ensure pam_pwhistory module is enabled | enable feature" - when: rhel8cis_authselect_current_history.rc != 0 + when: discovered_authselect_current_history.rc != 0 ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel8cis_authselect_custom_profile_name }}{% if rhel8cis_rule_4_4_2_2 %} with-faillock{% endif %}{% if rhel8cis_rule_4_4_2_3 %} with-pwquality{% endif %}{% if rhel8cis_rule_4_4_2_4 %} with-pwhistory{% endif %}{% if rhel8cis_rule_4_4_3_4_1 %} without-nullok{% endif %}" notify: Authselect update @@ -136,13 +136,13 @@ ansible.builtin.shell: | grep -P -- '\b(pam_unix\.so)\b' /etc/authselect/"$(head -1 /etc/authselect/authselect.conf)"/{system,password}-auth changed_when: false - failed_when: rhel8cis_authselect_pam_unix.rc not in [ 0, 1 ] - register: rhel8cis_authselect_pam_unix + failed_when: discovered_authselect_pam_unix.rc not in [ 0, 1 ] + register: discovered_authselect_pam_unix - name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled | system-auth" - when: "'system-auth:password' not in rhel8cis_authselect_pam_unix.stdout" + when: "'system-auth:password' not in discovered_uthselect_pam_unix.stdout" ansible.builtin.lineinfile: - path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/system-auth + path: /etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/system-auth regexp: "{{ item.regexp }}" line: "{{ item.line }}" backrefs: true From 4028a2d12c046a5d3667b850a73c5a9d95090460 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 25 Sep 2024 10:38:00 +0100 Subject: [PATCH 56/62] tidy up of variable naming Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.4.2.x.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasks/section_4/cis_4.4.2.x.yml b/tasks/section_4/cis_4.4.2.x.yml index d3e572f4..423e410e 100644 --- a/tasks/section_4/cis_4.4.2.x.yml +++ b/tasks/section_4/cis_4.4.2.x.yml @@ -61,7 +61,7 @@ - name: "4.4.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config" ansible.builtin.shell: authselect current | grep faillock changed_when: false - failed_when: discovered_uthselect_current_faillock.rc not in [ 0, 1 ] + failed_when: discovered_authselect_current_faillock.rc not in [ 0, 1 ] register: discovered_authselect_current_faillock - name: "4.4.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" @@ -140,7 +140,7 @@ register: discovered_authselect_pam_unix - name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled | system-auth" - when: "'system-auth:password' not in discovered_uthselect_pam_unix.stdout" + when: "'system-auth:password' not in discovered_authselect_pam_unix.stdout" ansible.builtin.lineinfile: path: /etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/system-auth regexp: "{{ item.regexp }}" @@ -154,9 +154,9 @@ notify: Authselect update - name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled | password-auth" - when: "'password-auth:password' not in rhel8cis_authselect_pam_unix.stdout" + when: "'password-auth:password' not in discovered_authselect_pam_unix.stdout" ansible.builtin.lineinfile: - path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/password-auth + path: /etc/authselect/custom/{{ rhel8cis_authselect_custom_profile_name }}/password-auth line: "{{ item.line }}" regexp: "{{ item.regexp }}" backrefs: true From 082eb26aeae6f3bcb2661580538c62b47178aec2 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 25 Sep 2024 10:41:11 +0100 Subject: [PATCH 57/62] Updated pipeline Signed-off-by: Mark Bolwell --- .github/workflows/devel_pipeline_validation.yml | 2 +- .github/workflows/main_pipeline_validation.yml | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index 07eae733..9a80bdc1 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -27,7 +27,7 @@ jobs: # This will create messages for first time contributers and direct them to the Discord server welcome: - runs-on: self-hosted + runs-on: ubuntu-latest steps: - uses: actions/first-interaction@main diff --git a/.github/workflows/main_pipeline_validation.yml b/.github/workflows/main_pipeline_validation.yml index 08433d90..9d7ea079 100644 --- a/.github/workflows/main_pipeline_validation.yml +++ b/.github/workflows/main_pipeline_validation.yml @@ -23,18 +23,6 @@ # A workflow run is made up of one or more jobs # that can run sequentially or in parallel jobs: - # This will create messages for first time contributers and direct them to the Discord server - welcome: - runs-on: self-hosted - - steps: - - uses: actions/first-interaction@main - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - pr-message: |- - Congrats on opening your first pull request and thank you for taking the time to help improve Ansible-Lockdown! - Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well. - # This workflow contains a single job that tests the playbook playbook-test: # The type of runner that the job will run on From ce3decbe13ee6c89927dd496d090eff7fab0d79c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 25 Sep 2024 10:45:58 +0100 Subject: [PATCH 58/62] removed quotes from boolean Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.1.x.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index d56d60a3..a0bddda0 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -252,7 +252,7 @@ ansible.builtin.shell: find {{ item.mount }} -xdev -nogroup -not -fstype nfs changed_when: false failed_when: false - check_mode: 'false' + check_mode: false register: discovered_ungrouped_items with_items: - "{{ ansible_facts.mounts }}" @@ -308,7 +308,7 @@ ansible.builtin.shell: find {{ item.mount }} -xdev -type f -perm -4000 -not -fstype nfs changed_when: false failed_when: false - check_mode: 'false' + check_mode: false register: discovered_suid_executables loop: "{{ ansible_facts.mounts }}" loop_control: @@ -318,7 +318,7 @@ ansible.builtin.shell: find {{ item.mount }} -xdev -type f -perm -2000 -not -fstype nfs changed_when: false failed_when: false - check_mode: 'false' + check_mode: false register: discovered_sgid_executables loop: "{{ ansible_facts.mounts }}" loop_control: From a30eba8256912373c3a077c4bd61e273f171fd7a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 7 Oct 2024 07:54:38 +0100 Subject: [PATCH 59/62] removed group from control not required Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.2.x.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/tasks/section_6/cis_6.2.x.yml b/tasks/section_6/cis_6.2.x.yml index befee5f1..e1fc4d90 100644 --- a/tasks/section_6/cis_6.2.x.yml +++ b/tasks/section_6/cis_6.2.x.yml @@ -341,7 +341,6 @@ path: "{{ item.dir }}" state: directory owner: "{{ item.id }}" - group: "{{ item.gid }}" loop: "{{ rhel8cis_passwd | selectattr('uid', '>=', rhel8uid_uid_start | int ) | selectattr('uid', '<=', rhel8uid_uid_stop | int ) | list }}" loop_control: label: "{{ item.id }}" From 41641976272b5ec470dfa7f86ca366c0a176eb2d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 18:26:58 +0000 Subject: [PATCH 60/62] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v4.6.0 → v5.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.6.0...v5.0.0) - [github.com/gitleaks/gitleaks: v8.19.2 → v8.20.1](https://github.com/gitleaks/gitleaks/compare/v8.19.2...v8.20.1) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bcbce980..e890b356 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ ci: repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: # Safety - id: detect-aws-credentials @@ -35,7 +35,7 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.19.2 + rev: v8.20.1 hooks: - id: gitleaks From 5b362c5515a6b9b414390e7e2c10bcb9a28a152f Mon Sep 17 00:00:00 2001 From: Roy Scheepers Date: Fri, 11 Oct 2024 17:26:24 +0200 Subject: [PATCH 61/62] fix typo in 2.2.17 Signed-off-by: Roy Scheepers --- tasks/section_2/cis_2.2.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_2/cis_2.2.x.yml b/tasks/section_2/cis_2.2.x.yml index 3860862a..208f5268 100644 --- a/tasks/section_2/cis_2.2.x.yml +++ b/tasks/section_2/cis_2.2.x.yml @@ -549,7 +549,7 @@ - name: "2.2.17 | PATCH | Ensure web proxy server services are not in use" when: - "'squid' in ansible_facts.packages" - - rhel8cis_rule_2_217 + - rhel8cis_rule_2_2_17 tags: - level1-server - level1-workstation From d3de1128f0d7f6315b827dbd7e97914e30b2e932 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 16 Oct 2024 15:31:35 +0100 Subject: [PATCH 62/62] updated 5.3.3 inline wth documentation Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.3.x.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tasks/section_5/cis_5.3.x.yml b/tasks/section_5/cis_5.3.x.yml index bb955a9e..754f57b4 100644 --- a/tasks/section_5/cis_5.3.x.yml +++ b/tasks/section_5/cis_5.3.x.yml @@ -85,10 +85,10 @@ path: /etc/aide.conf marker: "# {mark} Audit tools - CIS benchmark - Ansible-lockdown" block: | - /usr/sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512 - /usr/sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512 - /usr/sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512 - /usr/sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512 - /usr/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512 - /usr/sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512 + /sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512 + /sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512 + /sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512 + /sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512 + /sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512 + /sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512 validate: aide -D --config %s