diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 331d150..c25682f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,16 +39,16 @@ repos: rev: v1.5.0 hooks: - id: detect-secrets - name: Detect Secrets + name: Detect Secrets test - repo: https://github.com/gitleaks/gitleaks - rev: v8.24.3 + rev: v8.26.0 hooks: - id: gitleaks - name: GitLeaks + name: Run Gitleaks test - repo: https://github.com/ansible-community/ansible-lint - rev: v25.2.1 + rev: v25.5.0 hooks: - id: ansible-lint name: Ansible-lint @@ -67,7 +67,7 @@ repos: # - ansible-core>=2.10.1 - repo: https://github.com/adrienverge/yamllint.git - rev: v1.37.0 # or higher tag + rev: v1.37.1 # or higher tag hooks: - id: yamllint name: Check YAML Lint diff --git a/Changelog.md b/Changelog.md index d09b13d..8ca9c4f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,23 @@ # Changes to rhel9CIS +## 2.0.2 - Based on CIS v2.0.0 + +- Update to audit_only to allow fetching results +- resolved false warning for fetch audit +- fix root user check +- Improved documentation and variable compilation for crypto policies +- Addresses #318 - Thank you @kodebach & @bgro + - Improved logic for 5.2.4 to exclude rhel9cis_sudoers_exclude_nopasswd_list in pre-check tasks/main.yml +- rule_6.3.3.5 updated for missing checks + +## 2.0.1 - Based on CIS v2.0.0 + +- Thanks to @polski-g several issues and improvements added +- Improved testing for 50-redhat.conf for ssh +- 5.1.x regexp improvements +- Improved root password check +- egrep command changed to grep -E + ## 2.0.0 - Based on CIS v2.0.0 - #325 - thanks to @mindrb diff --git a/defaults/main.yml b/defaults/main.yml index 871e85e..23312e5 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -12,7 +12,7 @@ os_check: true # Disruption is high ## Run tests that are considered higher risk and could have a system impact if not properly tested ## Default false -## Will be fine if clean new unconfigured build +## Will be fine if clean new un-configured build rhel9cis_disruption_high: false ## Switching on/off specific baseline sections @@ -37,6 +37,7 @@ rhel9cis_level_2: true # Create managed not custom local_facts files create_benchmark_facts: true ansible_facts_path: /etc/ansible/facts.d + ## Section 1.6 - Mandatory Access Control # This variable governs whether SELinux is disabled or not. If SELinux is NOT DISABLED by setting # 'rhel9cis_selinux_disable' to 'true', the 1.6 subsection will be executed. @@ -111,7 +112,7 @@ audit_conf_dest: "/opt" # Where the audit logs are stored audit_log_dir: '/opt' -## Ability to collect and take audit files moving to a centralised location +## Ability to collect and take audit files moving to a centralized location # This enables the collection of the files from the host fetch_audit_output: false @@ -238,7 +239,7 @@ rhel9cis_rule_1_8_8: true rhel9cis_rule_1_8_9: true rhel9cis_rule_1_8_10: true -# Section 2 rules are controlling Services (Special Purpose Services, and service clients) +# Section 2 rules are controling Services (Special Purpose Services, and service clients) ## Configure Server Services rhel9cis_rule_2_1_1: true rhel9cis_rule_2_1_2: true @@ -513,7 +514,7 @@ rhel9cis_rule_7_2_9: true ## Section 1 vars -## Ability to enabe debug on mounts to assist in troubleshooting +## Ability to enable debug on mounts to assist in troubleshooting # Mount point changes are set based upon facts created in Prelim # these then build the variable and options that is passed to the handler to set the mount point for the controls in section1. rhel9cis_debug_mount_data: false @@ -579,8 +580,8 @@ rhel9cis_crypto_policy: 'DEFAULT' ## Control 1.6 # This variable contains the value of the crypto policy module(combinations of policies and # sub-policies) to be allowed as default setting. Allowed options are defined in 'vars/main.yml' file, -# using 'rhel9cis_allowed_crypto_policies_modules' variable. -rhel9cis_crypto_policy_module: '' +# using those listed in the 'rhel9cis_allowed_crypto_policies_modules' variable. +rhel9cis_additional_crypto_policy_module: '' ## Controls: # - 1.7.1 - Ensure message of the day is configured properly @@ -723,6 +724,7 @@ rhel9cis_ipv6_required: true ## 3.1.2 wireless network requirements # if wireless adapter found allow network manager to be installed rhel9cis_install_network_manager: false +rhel9cis_network_manager_package_name: NetworkManager # 3.3 System network parameters (host only OR host and router) # This variable governs whether specific CIS rules # concerned with acceptance and routing of packages are skipped. @@ -1045,14 +1047,14 @@ rhel9cis_bash_umask: '0027' # 0027 or more restrictive # These are discovered via logins.def if set true rhel9cis_discover_int_uid: true # This variable sets the minimum number from which to search for UID -# Note that the value will be dynamically overwritten if variable `dicover_int_uid` has +# Note that the value will be dynamically overwritten if variable `rhel9cis_discover_int_uid` has # been set to `true`. min_int_uid: 1000 ### Controls: # - Ensure local interactive user home directories exist # - Ensure local interactive users own their home directories # This variable sets the maximum number at which the search stops for UID -# Note that the value will be dynamically overwritten if variable `dicover_int_uid` has +# Note that the value will be dynamically overwritten if variable `rhel9cis_discover_int_uid` has # been set to `true`. max_int_uid: 65533 diff --git a/handlers/main.yml b/handlers/main.yml index 1a3b66e..71f5554 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -150,7 +150,7 @@ ansible.posix.mount: path: "{{ mount_point }}" state: remounted - notify: Change_requires_reboot + notify: Set reboot required listen: "Remount /boot/efi" - name: Reload sysctl @@ -186,7 +186,7 @@ - name: Update Crypto Policy ansible.builtin.set_fact: - rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{% if rhel9cis_crypto_policy_module | length > 0 %}{{ rhel9cis_crypto_policy_module }}{% endif %}" + rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{{ rhel9cis_crypto_policy_module }}{% if rhel9cis_additional_crypto_policy_module | length > 0 %}:{{ rhel9cis_additional_crypto_policy_module }}{% endif %}" notify: Set Crypto Policy - name: Set Crypto Policy @@ -194,7 +194,7 @@ ansible.builtin.command: update-crypto-policies --set "{{ rhel9cis_full_crypto_policy }}" changed_when: true notify: - - Change_requires_reboot + - Set reboot required - Restart sshd - name: Restart firewalld @@ -255,7 +255,7 @@ when: discovered_auditd_immutable_check.stdout == '1' ansible.builtin.debug: msg: "Reboot required for auditd to apply new rules as immutable set" - notify: Change_requires_reboot + notify: Set reboot required - name: Stop auditd process ansible.builtin.command: systemctl kill auditd @@ -268,6 +268,6 @@ state: started listen: Restart auditd -- name: Change_requires_reboot +- name: Set reboot required ansible.builtin.set_fact: change_requires_reboot: true diff --git a/site.yml b/site.yml index f3f0fae..4386b04 100644 --- a/site.yml +++ b/site.yml @@ -1,7 +1,7 @@ --- - name: Apply ansible-lockdown hardening - hosts: all + hosts: "{{ hosts | default('all') }}" become: true roles: - role: "{{ playbook_dir }}" diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index 845d9d9..a33cb94 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -1,20 +1,17 @@ --- -- name: Audit_Only | Create local Directories for hosts - when: fetch_audit_files - ansible.builtin.file: - mode: 'u+x,go-w' - path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}" - recurse: true - state: directory - delegate_to: localhost - become: false +- name: Audit_only | Fetch audit files + when: + - fetch_audit_output + - audit_only + ansible.builtin.import_tasks: + file: fetch_audit_output.yml - name: Audit_only | Show Audit Summary when: audit_only ansible.builtin.debug: msg: "{{ audit_results.split('\n') }}" -- name: Audit_only | Stop Playbook Audit Only selected +- name: Audit_only | Stop task for host as audit_only selected when: audit_only - ansible.builtin.meta: end_play + ansible.builtin.meta: end_host diff --git a/tasks/auditd.yml b/tasks/auditd.yml index 7b86b94..0fa0b32 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -7,6 +7,7 @@ - name: "POST | AUDITD | Set supported_syscalls variable" ansible.builtin.shell: ausyscall --dump | awk '{print $2}' changed_when: false + check_mode: false failed_when: discovered_auditd_syscalls.rc not in [ 0, 1 ] register: discovered_auditd_syscalls diff --git a/tasks/fetch_audit_output.yml b/tasks/fetch_audit_output.yml index 563b699..e440185 100644 --- a/tasks/fetch_audit_output.yml +++ b/tasks/fetch_audit_output.yml @@ -8,6 +8,7 @@ src: "{{ item }}" dest: "{{ audit_output_destination }}" flat: true + changed_when: true failed_when: false register: discovered_audit_fetch_state loop: diff --git a/tasks/main.yml b/tasks/main.yml index f9f2bd2..9582bed 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -59,7 +59,7 @@ - crypto - NIST800-53R5_SC-6 ansible.builtin.assert: - that: rhel9cis_crypto_policy_module in rhel9cis_allowed_crypto_policies_modules + that: rhel9cis_additional_crypto_policy_module in rhel9cis_allowed_crypto_policies_modules fail_msg: "Crypto policy module is not a permitted version" success_msg: "Crypto policy module is a permitted version" @@ -99,10 +99,9 @@ - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" # noqa name[template] ansible.builtin.assert: - that: - - not prelim_ansible_user_password_set.stdout.startswith("!") + that: (not prelim_ansible_user_password_set.stdout.startswith("!")) or (ansible_env.SUDO_USER in rhel9cis_sudoers_exclude_nopasswd_list) fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} is locked - It can break access" - success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} user" + success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} is not locked or included in the exception list for rule 5.2.4" - name: "Check authselect profile is selected" when: rhel9cis_allow_authselect_updates @@ -130,7 +129,7 @@ - rule_5.4.2.4 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)" changed_when: false register: prelim_root_passwd_set diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 9190421..c7ed865 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -7,12 +7,12 @@ ansible.builtin.shell: cat /etc/passwd | grep -v '^#' changed_when: false check_mode: false - register: prelim_passwd_file_audit + register: prelim_capture_passwd_file - - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries" + - name: "PRELIM | 5.4.2 | 7.2.8 | Split passwd entries" ansible.builtin.set_fact: - rhel9cis_passwd: "{{ prelim_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" - loop: "{{ prelim_passwd_file_audit.stdout_lines }}" + prelim_captured_passwd_data: "{{ prelim_capture_passwd_file.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" + loop: "{{ prelim_capture_passwd_file.stdout_lines }}" vars: ld_passwd_regex: >- ^(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*) diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 61959fa..80df209 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -1,4 +1,5 @@ --- + - name: Pre Audit Setup | Setup the LE audit when: setup_audit tags: setup_audit @@ -46,7 +47,7 @@ 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 +- name: Pre Audit Setup | Check goss is available when: run_audit block: - name: Pre Audit Setup | Check for goss file diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 9b19bf1..80decfd 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -4,9 +4,7 @@ # List users in order to look files inside each home directory - name: "PRELIM | Include audit specific variables" - when: - - run_audit or audit_only - - setup_audit + when: run_audit or audit_only or setup_audit tags: - setup_audit - run_audit @@ -14,9 +12,7 @@ file: audit.yml - name: "PRELIM | Include pre-remediation audit tasks" - when: - - run_audit or audit_only - - setup_audit + when: run_audit or audit_only or setup_audit tags: run_audit ansible.builtin.import_tasks: pre_remediation_audit.yml @@ -31,9 +27,17 @@ - name: "PRELIM | AUDIT | Interactive Users (reformat)" tags: always ansible.builtin.set_fact: - prelim_interactive_usernames: "{{ prelim_interactive_users | default([]) + [dict([('username', item.split(':')[0]), ('uid', item.split(':')[1]), ('home', item.split(':')[2])])] }}" + prelim_interactive_users: "{{ prelim_interactive_users | default([]) + [dict([('username', item.split(':')[0]), ('uid', item.split(':')[1]), ('home', item.split(':')[2])])] }}" loop: "{{ prelim_interactive_users_raw.stdout_lines }}" +- 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 + check_mode: false + register: prelim_interactive_users_home + - name: "PRELIM | AUDIT | Interactive UIDs" tags: always ansible.builtin.shell: > @@ -132,8 +136,7 @@ register: prelim_systemd_coredump - name: "PRELIM | PATCH | Setup crypto-policy" - when: - - rhel9cis_rule_1_6_1 + when: rhel9cis_rule_1_6_1 tags: - level1-server - level1-workstation @@ -181,17 +184,14 @@ grub2_path: /etc/grub2-efi.cfg - name: "PRELIM | AUDIT | Discover Gnome Desktop Environment" - tags: - - always + tags: always ansible.builtin.stat: path: /usr/share/gnome/gnome-version.xml register: prelim_gnome_present - name: "PRELIM | PATCH | Install dconf if gui installed" - when: - - rhel9cis_gui - tags: - - always + when: rhel9cis_gui + tags: always ansible.builtin.package: name: dconf state: present @@ -200,10 +200,9 @@ when: - rhel9cis_rule_3_1_2 - not system_is_container - tags: - - always + tags: always block: - - name: "PRELIM | AUDIT | Discover is wirelss adapter on system" + - name: "PRELIM | AUDIT | Discover is wireless adapter on system" ansible.builtin.command: find /sys/class/net/*/ -type d -name wireless register: discover_wireless_adapters changed_when: false @@ -246,6 +245,12 @@ mode: 'go-rwx' state: touch +- name: "PRELIM | PATCH | sshd_config.d/50-redhat.conf exists" + when: rhel9cis_rule_5_1_10 or rhel9cis_rule_5_1_11 + ansible.builtin.stat: + path: /etc/ssh/sshd_config.d/50-redhat.conf + register: prelim_sshd_50_redhat_file + - name: "PRELIM | AUDIT | Capture pam security related files" tags: always ansible.builtin.find: @@ -269,8 +274,7 @@ - name: "PRELIM | PATCH | Create journald config directory" when: - rhel9cis_syslog == 'journald' - - rhel9cis_rule_6_2_1_3 or - rhel9cis_rule_6_2_1_4 + - rhel9cis_rule_6_2_1_3 or rhel9cis_rule_6_2_1_4 tags: always ansible.builtin.file: path: /etc/systemd/journald.conf.d diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index adc094d..e67bb39 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -27,8 +27,7 @@ mode: 'go-rwx' - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | Disable cramfs" - when: - - not system_is_container + when: not system_is_container community.general.modprobe: name: cramfs state: absent 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 998d1ba..635648d 100644 --- a/tasks/section_1/cis_1.1.2.3.x.yml +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -21,12 +21,12 @@ register: discovered_home_mount - name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | Absent" - when: discovered_dev_shm_mount is undefined + when: discovered_home_mount is undefined ansible.builtin.debug: msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" - name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | Present" - when: discovered_dev_shm_mount is undefined + when: discovered_home_mount is undefined ansible.builtin.import_tasks: file: 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 e0afd4e..f89fe3f 100644 --- a/tasks/section_1/cis_1.1.2.4.x.yml +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -22,12 +22,12 @@ register: discovered_var_mount - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Absent" - when: discovered_dev_shm_mount is undefined + when: discovered_var_mount is undefined ansible.builtin.debug: msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Present" - when: discovered_dev_shm_mount is undefined + when: discovered_var_mount is undefined ansible.builtin.import_tasks: file: warning_facts.yml diff --git a/tasks/section_1/cis_1.2.2.x.yml b/tasks/section_1/cis_1.2.2.x.yml index 2ccb59f..379b92d 100644 --- a/tasks/section_1/cis_1.2.2.x.yml +++ b/tasks/section_1/cis_1.2.2.x.yml @@ -13,4 +13,4 @@ ansible.builtin.package: name: "*" state: latest - notify: Change_requires_reboot + notify: Set reboot required diff --git a/tasks/section_1/cis_1.3.1.x.yml b/tasks/section_1/cis_1.3.1.x.yml index 198ae7b..ad7d844 100644 --- a/tasks/section_1/cis_1.3.1.x.yml +++ b/tasks/section_1/cis_1.3.1.x.yml @@ -106,7 +106,7 @@ warn_control_id: '1.3.1.6' block: - name: "1.3.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 }' + ansible.builtin.shell: ps -eZ | grep unconfined_service_t | grep -Evw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }' register: discovered_unconf_services failed_when: false changed_when: false diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index 68a66de..a20c0e9 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -39,7 +39,7 @@ warn_control_id: '3.1.2' block: - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Check for network-manager tool" - when: "'network-manager' in ansible_facts.packages" + when: "rhel9cis_network_manager_package_name in ansible_facts.packages" ansible.builtin.command: nmcli radio wifi changed_when: false failed_when: false @@ -48,19 +48,19 @@ - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Disable wireless if network-manager installed" when: - - "'network-manager' in ansible_facts.packages" + - "rhel9cis_network_manager_package_name in ansible_facts.packages" - "'enabled' in discovered_wifi_status.stdout" ansible.builtin.command: nmcli radio all off changed_when: discovered_nmcli_radio_off.rc == 0 register: discovered_nmcli_radio_off - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Warn about wireless if network-manager not installed" - when: "'network-manager' not in ansible_facts.packages" + when: "rhel9cis_network_manager_package_name not in ansible_facts.packages" ansible.builtin.debug: msg: "Warning!! You need to disable wireless interfaces manually since network-manager is not installed" - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Set warning count" - when: "'network-manager' not in ansible_facts.packages" + when: "rhel9cis_network_manager_package_name not in ansible_facts.packages" ansible.builtin.import_tasks: file: warning_facts.yml diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index 99176fd..3fd366c 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -276,9 +276,10 @@ notify: Restart sshd - name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled | override" + when: prelim_sshd_50_redhat_file.stat.exists ansible.builtin.lineinfile: path: /etc/ssh/sshd_config.d/50-redhat.conf - regexp: ^(?i)(#|)\s*X11Forwarding + regexp: (?i)^(#|)\s*X11Forwarding line: 'X11Forwarding {{ rhel9cis_sshd_x11forwarding }}' validate: sshd -t -f %s notify: Restart sshd @@ -298,9 +299,10 @@ - NIST800-53R5_IA-5 block: - name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled | redhat file" + when: prelim_sshd_50_redhat_file.stat.exists ansible.builtin.lineinfile: path: /etc/ssh/sshd_config.d/50-redhat.conf - regexp: ^(?i)(#|)\s*GSSAPIAuthentication + regexp: (?i)^(#|)\s*GSSAPIAuthentication line: GSSAPIAuthentication no validate: sshd -t -f %s notify: Restart sshd @@ -308,7 +310,7 @@ - name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled | ssh config" ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*GSSAPIAuthentication + regexp: (?i)^(#|)\s*GSSAPIAuthentication line: GSSAPIAuthentication no validate: sshd -t -f %s notify: Restart sshd @@ -328,7 +330,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*HostbasedAuthentication + regexp: (?i)^(#|)\s*HostbasedAuthentication line: 'HostbasedAuthentication no' validate: sshd -t -f %s notify: Restart sshd @@ -348,7 +350,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*IgnoreRhosts + regexp: (?i)^(#|)\s*IgnoreRhosts line: 'IgnoreRhosts yes' insertbefore: "^Match" firstmatch: true @@ -366,7 +368,7 @@ - NIST800-53R5_CM-6 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*LoginGraceTime + regexp: (?i)^(#|)\s*LoginGraceTime line: "LoginGraceTime {{ rhel9cis_sshd_logingracetime }}" insertbefore: "^Match" firstmatch: true @@ -386,7 +388,7 @@ - NIST800-53R5_SI-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*LogLevel + regexp: (?i)^(#|)\s*LogLevel line: 'LogLevel {{ rhel9cis_ssh_loglevel }}' insertbefore: "^Match" firstmatch: true @@ -424,7 +426,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*MaxStartups + regexp: (?i)^(#|)\s*MaxStartups line: 'MaxStartups {{ rhel9cis_ssh_maxstartups }}' validate: sshd -t -f %s notify: Restart sshd @@ -444,7 +446,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*MaxSessions + regexp: (?i)^(#|)\s*MaxSessions line: 'MaxSessions {{ rhel9cis_ssh_maxsessions }}' validate: sshd -t -f %s notify: Restart sshd @@ -464,7 +466,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*PermitEmptyPasswords + regexp: (?i)^(#|)\s*PermitEmptyPasswords line: 'PermitEmptyPasswords no' validate: sshd -t -f %s notify: Restart sshd @@ -482,7 +484,7 @@ - name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled | config file" ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*PermitRootLogin + regexp: (?i)^(#|)\s*PermitRootLogin line: 'PermitRootLogin no' validate: sshd -t -f %s notify: Restart sshd @@ -508,7 +510,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*PermitUserEnvironment + regexp: (?i)^(#|)\s*PermitUserEnvironment line: 'PermitUserEnvironment no' validate: sshd -t -f %s notify: Restart sshd @@ -528,7 +530,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*UsePAM + regexp: (?i)^(#|)\s*UsePAM line: 'UsePAM yes' validate: sshd -t -f %s notify: Restart sshd diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index 1962101..7fcfb0b 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -29,7 +29,7 @@ - name: "5.4.1.1 | PATCH | Ensure password expiration is 365 days or less | Set existing users PASS_MAX_DAYS" when: - discovered_max_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames | map(attribute='username') | list + - item in prelim_interactive_users | map(attribute='username') | list - rhel9cis_force_user_maxdays ansible.builtin.user: name: "{{ item }}" @@ -60,7 +60,7 @@ - name: "5.4.1.2 | PATCH | Ensure minimum password days is configured | Set existing users PASS_MIN_DAYS" when: - discovered_min_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames | map(attribute='username') | list + - item in prelim_interactive_users | map(attribute='username') | list - rhel9cis_force_user_mindays ansible.builtin.user: name: "{{ item }}" @@ -91,7 +91,7 @@ - name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured | Set existing users WARN_DAYS" when: - discovered_warn_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames | map(attribute='username') | list + - item in prelim_interactive_users | map(attribute='username') | list - rhel9cis_force_user_warnage ansible.builtin.command: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" changed_when: true @@ -140,7 +140,7 @@ register: discovered_passwdlck_user_list - name: "5.4.1.5 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts" - when: item in prelim_interactive_usernames | map(attribute='username') | list + when: item in prelim_interactive_users | map(attribute='username') | list ansible.builtin.command: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}" changed_when: true loop: "{{ discovered_passwdlck_user_list.stdout_lines }}" diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index a8eb4d0..37a4e11 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -195,7 +195,7 @@ - name: "5.4.2.7 | PATCH | Ensure system accounts do not have a valid login shell" when: - rhel9cis_rule_5_4_2_7 - - "item.id not in prelim_interactive_usernames | map(attribute='username')" + - "item.id not in prelim_interactive_users | map(attribute='username')" - item.id not in rhel9cis_system_users_shell - "'root' not in item.id" - rhel9cis_disruption_high @@ -212,7 +212,7 @@ ansible.builtin.user: name: "{{ item.id }}" shell: /usr/sbin/nologin - loop: "{{ rhel9cis_passwd }}" + loop: "{{ prelim_captured_passwd_data }}" loop_control: label: "{{ item.id }}" @@ -220,7 +220,7 @@ when: - rhel9cis_rule_5_4_2_8 - rhel9cis_disruption_high - - "item.id not in prelim_interactive_usernames | map(attribute='username')" + - "item.id not in prelim_interactive_users | map(attribute='username')" - "'root' not in item.id" tags: - level1-server @@ -235,6 +235,6 @@ ansible.builtin.user: name: "{{ item.id }}" password_lock: true - loop: "{{ rhel9cis_passwd }}" + loop: "{{ prelim_captured_passwd_data }}" loop_control: label: "{{ item.id }}" diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml index 8706877..3be2ad3 100644 --- a/tasks/section_7/cis_7.2.x.yml +++ b/tasks/section_7/cis_7.2.x.yml @@ -220,7 +220,7 @@ - name: "7.2.7 | AUDIT | Ensure no duplicate group names exist | Print warning about users with duplicate group names" when: discovered_group_check.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following group names are duplicates: {{ discovered_group_group_check.stdout_lines }}" + msg: "Warning!! The following group names are duplicates: {{ discovered_group_check.stdout_lines }}" - name: "7.2.7 | AUDIT | Ensure no duplicate group names exist | Set warning count" when: discovered_group_check.stdout | length > 0 @@ -243,7 +243,7 @@ state: directory owner: "{{ item.id }}" group: "{{ item.gid }}" - loop: "{{ rhel9cis_passwd | selectattr('uid', '>=', prelim_min_int_uid | int) | selectattr('uid', '<=', prelim_max_int_uid | int) | list }}" + loop: "{{ prelim_captured_passwd_data | selectattr('uid', '>=', prelim_min_int_uid | int) | selectattr('uid', '<=', prelim_max_int_uid | int) | list }}" loop_control: label: "{{ item.id }}" @@ -315,6 +315,6 @@ ansible.builtin.file: path: '{{ item }}' mode: 'go-w' - owner: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_raw.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" - group: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_raw.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" + owner: "{{ prelim_captured_passwd_data | selectattr('dir', 'in', prelim_interactive_users_raw.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" + group: "{{ prelim_captured_passwd_data | selectattr('dir', 'in', prelim_interactive_users_raw.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" with_items: "{{ discovered_homedir_hidden_files.stdout_lines }}" diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 4d9c0d3..4fa4516 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -56,8 +56,10 @@ -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/hostname -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/NetworkManager -p wa -k system-locale {% endif %} {% if rhel9cis_rule_6_3_3_6 %} {% for proc in discovered_priv_procs.stdout_lines -%} diff --git a/vars/main.yml b/vars/main.yml index 5eed07c..9337d58 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -7,10 +7,16 @@ rhel9cis_allowed_crypto_policies: - 'FUTURE' - 'FIPS' +# Following is left blank for ability to build string +rhel9cis_crypto_policy_module: '' + +# Do not adjust these are recognized as part of the CIS benchmark and used during testing rhel9cis_allowed_crypto_policies_modules: + # Recognized by CIS as possible extra options - 'OSPP' - 'AD-SUPPORT' - 'AD-SUPPORT-LEGACY' + # The following are already included in 1.6.x controls - 'NO-SHA1' - 'NO-SSHCBC' - 'NO-SSHETM'