diff --git a/defaults/main.yml b/defaults/main.yml index 04f8f71..b836238 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -641,7 +641,7 @@ rhel9cis_chrony_server_minsources: 2 # # Setting both Service and Mask to false will remove the package if exists rhel9cis_autofs_services: false -rhel9cis_autofs_mask: true +rhel9cis_autofs_mask: false rhel9cis_avahi_server: false rhel9cis_avahi_mask: false rhel9cis_dhcp_server: false @@ -860,7 +860,7 @@ rhel9cis_sudoers_exclude_nopasswd_list: ## Control 5.2 - Ensure access to the 'su' command is restricted # This variable determines the name of the group of users that are allowed to use the su command. # CIS requires that such a group be CREATED(named according to site policy) and be kept EMPTY. -rhel9cis_sugroup: nosugroup +rhel9cis_sugroup: sugroup ## 5.3.x PAM and Authselect # Do not use authselect if: @@ -868,10 +868,30 @@ rhel9cis_sugroup: nosugroup # 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. -rhel9cis_allow_authselect_updates: false +rhel9cis_allow_authselect_updates: true ## rhel9cis_authselect_pkg_update: false # NOTE the risks if system is using SSSD or using ipa-client-install + +## 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 +rhel9cis_authselect_custom_profile_create: true +## Controls: +# - 5.3.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 +rhel9cis_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 +rhel9cis_authselect_default_profile_to_copy: "sssd --symlink-meta" + ## Controls # - 5.3.3. - Ensure lockout for failed password attempts is configured # - 5.5.3 - Ensure password reuse is limited @@ -905,7 +925,12 @@ rhel9cis_passwd_minlen_value: 14 # 5.3.3.2.3 - password complex rhel9cis_passwd_complex_file: etc/security/pwquality.conf.d/50-pwcomplexity.conf # pragma: allowlist secret +# Choose if using minclass or credits options +# Options are: minclass or credits +# ensure only one is selected +rhel9cis_passwd_complex_option: minclass rhel9cis_passwd_minclass: 3 +#rhel9cis_passwd_complex: credits rhel9cis_passwd_dcredit: -1 rhel9cis_passwd_ucredit: -2 rhel9cis_passwd_ocredit: 0 @@ -931,6 +956,11 @@ rhel9cis_passwd_quality_enforce_value: 1 rhel9cis_passwd_quality_enforce_root_file: etc/security/pwquality.conf.d/50-pwroot.conf # pragma: allowlist secret rhel9cis_passwd_quality_enforce_root_value: enforce_for_root # pragma: allowlist secret +# PWhistory +## 5.3.3.3.1 remember history +# rhel9cis_pamd_pwhistory_remember: - is the number of old passwords to remember +rhel9cis_pamd_pwhistory_remember: 24 + # 5.3.3.4.x rhel9cis_passwd_hash_algo: sha512 # pragma: allowlist secret diff --git a/tasks/main.yml b/tasks/main.yml index 6a28be4..488c765 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -112,6 +112,29 @@ 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" +- name: "PRELIM | AUDIT | Check authselect profile is selected" + when: + - rhel9cis_allow_authselect_updates + tags: + - always + block: + - name: "PRELIM | AUDIT | Check authselect profile name has been updated" + ansible.builtin.assert: + that: rhel9cis_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 + changed_when: false + failed_when: prelim_authselect_current_config.rc not in [ 0, 1 ] + register: prelim_authselect_current_config + + - name: "PRELIM | AUDIT | Check authselect profile is selected" + ansible.builtin.assert: + that: prelim_authselect_current_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: "Ensure root password is set" when: - rhel9cis_rule_5_4_2_4 diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index 3f318c9..3bc8ec0 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -14,19 +14,28 @@ - rule_5.3.2.1 block: - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Create custom profiles" - when: - - "rhel9cis_authselect['custom_profile_name'] not in authselect_running_config.stdout" - - rhel9cis_authselect_custom_profile_create - - not rhel9cis_5_3_2_1_profile.stat.exists - ansible.builtin.shell: "/usr/bin/authselect create-profile {{ rhel9cis_authselect['custom_profile_name'] }} -b {{ rhel9cis_authselect['default_file_to_copy'] }}" + when: prelim_authselect_current_config.stdout is not defined + ansible.builtin.shell: "/usr/bin/authselect create-profile {{ rhel9cis_authselect_custom_profile_name }} -b {{ rhel9cis_authselect_default_profile_to_copy }}" args: - creates: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}" + creates: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}" - - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Select profiles" - when: - - "rhel9cis_authselect['custom_profile_name'] not in authselect_running_config.stdout" - - rhel9cis_authselect_custom_profile_select - ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %} --force" + - name: "5.3.2.1 | AUDIT | Ensure active authselect profile includes pam modules | get profile features" + ansible.builtin.shell: "/usr/bin/authselect list-features custom/{{ rhel9cis_authselect_custom_profile_name }}" + changed_when: false + register: discovered_authselect_profile_features + + - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | 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/{{ rhel9cis_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: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Backup and Add pam modules" + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %} --force --backup=rhel9cis-preremediate-{{ lookup('pipe', 'date +%Y-%m-%d-%H%M') }}" - name: "5.3.2.2 | PATCH | Ensure pam_faillock module is enabled" when: @@ -45,17 +54,17 @@ - NIST800-53R5_IA-5 - authselect - rule_5.3.2.2 - notify: Update_authselect + notify: Authselect update block: - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config" ansible.builtin.shell: authselect current | grep faillock changed_when: false - failed_when: rhel9cis_authselect_current.rc not in [ 0, 1 ] - register: rhel9cis_authselect_current + failed_when: rhel9cis_authselect_current_faillock.rc not in [ 0, 1 ] + register: rhel9cis_authselect_current_faillock - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" - when: rhel9cis_authselect_current.rc != 0 - ansible.builtin.shell: "authselect enable-feature with-faillock" + when: rhel9cis_authselect_current_faillock.rc != 0 + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled" when: @@ -70,62 +79,17 @@ - NIST800-53R5_IA-5 - authselect - rule_5.3.2.3 - notify: Update_authselect block: - name: "5.3.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Get current config" ansible.builtin.shell: authselect current | grep quality changed_when: false - failed_when: rhel9cis_authselect_current.rc not in [ 0, 1 ] - register: rhel9cis_authselect_current + failed_when: rhel9cis_authselect_current_quality.rc not in [ 0, 1 ] + register: rhel9cis_authselect_current_quality - name: "5.3.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Add feature if missing" - when: rhel9cis_authselect_current.rc != 0 - ansible.builtin.shell: "authselect enable-feature with-pwquality" - -# - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled" -# when: -# - rhel9cis_rule_5_3_2_3 -# - rhel9cis_disruption_high -# - rhel9cis_allow_authselect_updates -# tags: -# - level1-server -# - level1-workstation -# - automated -# - patch -# - NIST800-53R5_IA-5 -# - authselect -# - rule_5.3.2.3 -# notify: Update_authselect -# block: -# - name: "5.3.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: rhel9cis_pwquality_enabled.rc not in [ 0, 1 ] -# register: rhel9cis_pwquality_enabled - -# - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled | system-auth" -# when: "'system-auth:password' not in rhel9cis_pwquality_enabled.stdout" -# ansible.builtin.lineinfile: -# path: /etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth -# regexp: "{{ item.regexp }}" -# line: "{{ item.line }}" -# backrefs: true -# insertbefore: "{{ item.before | default (omit) }}" -# 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: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled | password-auth" -# when: "'password-auth:password' not in rhel9cis_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/{{ rhel9cis_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]' } + when: rhel9cis_authselect_current_quality.rc != 0 + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + notify: Authselect update - name: "5.3.2.4 | PATCH | Ensure pam_pwhistory module is enabled" when: @@ -140,17 +104,17 @@ - NIST800-53R5_IA-5 - authselect - rule_5.3.2.4 - notify: Update_authselect block: - name: "5.3.2.4 | AUDIT | Ensure pam_pwhistory module is enabled | Get current config" ansible.builtin.shell: authselect current | grep pwhistory changed_when: false - failed_when: rhel9cis_authselect_current.rc not in [ 0, 1 ] - register: rhel9cis_authselect_current + failed_when: rhel9cis_authselect_current_history.rc not in [ 0, 1 ] + register: rhel9cis_authselect_current_history - name: "5.3.2.4 | PATCH | Ensure pam_pwhistory module is enabled | enable feature" - when: rhel9cis_authselect_current.rc != 0 - ansible.builtin.shell: "authselect enable-feature with-pwhistory" + when: rhel9cis_authselect_current_history.rc != 0 + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + notify: Authselect update - name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled" when: @@ -173,6 +137,9 @@ failed_when: rhel9cis_authselect_pam_unix.rc not in [ 0, 1 ] register: rhel9cis_authselect_pam_unix + - debug: + msg: "{{ rhel9cis_authselect_pam_unix }}" + - name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled | system-auth" when: "'system-auth:password' not in rhel9cis_authselect_pam_unix.stdout" ansible.builtin.lineinfile: @@ -185,6 +152,7 @@ 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: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled | password-auth" when: "'password-auth:password' not in rhel9cis_authselect_pam_unix.stdout" @@ -198,3 +166,4 @@ 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_5/cis_5.3.3.3.x.yml b/tasks/section_5/cis_5.3.3.3.x.yml index ffb1bff..6c04d33 100644 --- a/tasks/section_5/cis_5.3.3.3.x.yml +++ b/tasks/section_5/cis_5.3.3.3.x.yml @@ -16,16 +16,11 @@ changed_when: false failed_when: rhel9_pwhistory_remember.rc not in [0, 1] - - name: "5.3.3.3.1 | PATCH | Ensure password number of changed characters is configured | Ensure remember is set" - when: - - rhel9_pwhistory_remember.stdout | length > 0 - - not rhel9cis_allow_authselect_updates + - name: "5.3.3.3.1 | PATCH | Ensure password number of changed characters is configured | Ensure remember is set pwhistory file" ansible.builtin.lineinfile: - path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" - regexp: ^(password\s+[^#\n\r]+\h+pam_pwhistory\.so\s+)(.*)(remember=\d+) - line: '\1\2 remember={{ rhel9cis_pamd_pwhistory_remember }}' - backrefs: true - notify: Pam_auth_update_pwhistory + path: "/etc/security/pwhistory.conf" + regexp: remember\s*=\s*\d* + line: remember = {{ rhel9cis_pamd_pwhistory_remember }} - name: "5.3.3.3.1 | PATCH | Ensure password number of changed characters is configured | Remove remember from pam files NOT AuthSelect" when: @@ -55,7 +50,6 @@ - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user" when: - rhel9cis_rule_5_3_3_3_2 - - rhel9cis_disruption_high tags: - level1-server - level1-workstation @@ -69,26 +63,45 @@ changed_when: false failed_when: rhel9_pwhistory_enforce_for_root.rc not in [0, 1] - - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user | Ensure remember is set" + - name: "5.3.3.3.2 | PATCH| Ensure password history is enforced for the root user | Ensure enforce_for_root is set pwhistory file" + ansible.builtin.lineinfile: + path: "/etc/security/pwhistory.conf" + regexp: ^\s*(?#)enforce_for_root + line: enforce_for_root + + - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user | Ensure enforce_for_root is set" when: - not rhel9cis_allow_authselect_updates - - rhel9_pwhistory_enforce_for_root.stdout | length > 0 + - rhel9_pwhistory_enforce_for_root.stdout | length == 0 + - rhel9cis_disruption_high ansible.builtin.lineinfile: path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" regexp: ^(password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+)(.*)(enforce_for_root) line: '\1\2\3 enforce_for_root' backrefs: true - notify: Pam_auth_update_pwhistory + + - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user | Ensure enforce_for_root is set" + when: + - rhel9cis_allow_authselect_updates + - rhel9_pwhistory_enforce_for_root.stdout | length == 0 + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\senforce_for_root(.*$) + replace: \1\2enforce_for_root\3 + loop: + - password + - system + notify: Authselect update - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok" when: - rhel9cis_rule_5_3_3_3_3 - - rhel9cis_disruption_high tags: - level1-server - level1-workstation - patch - - rule_5.3.3.3.2 + - rule_5.3.3.3.3 - pam block: - name: "5.3.3.3.3 | AUDIT | Ensure pam_pwhistory includes use_authtok | Check existing files" @@ -97,20 +110,27 @@ changed_when: false failed_when: rhel9_pwhistory_use_authtok.rc not in [0, 1] - - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | Ensure remember is set" + - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | Update pwhistory for use_authtok" + ansible.builtin.lineinfile: + path: "/etc/security/pwhistory.conf" + regexp: ^\s*(?#)use_authtok + line: use_authtok + + - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | Ensure use_authtok is set" when: - not rhel9cis_allow_authselect_updates - - rhel9_pwhistory_use_authtok.stdout | length > 0 + - rhel9_pwhistory_use_authtok.stdout | length == 0 + - rhel9cis_disruption_high ansible.builtin.lineinfile: path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" regexp: ^(password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+)(.*)(use_authtok) - line: '\1\2\3 use_authtok' + line: '\1\2 use_authtok' backrefs: true - notify: Pam_auth_update_pwhistory - name: "PATCH | Ensure pam_pwhistory includes use_authtok | add authtok to pam files AuthSelect" when: - rhel9cis_allow_authselect_updates + - rhel9_pwhistory_use_authtok.stdout | length == 0 - rhel9cis_disruption_high ansible.builtin.lineinfile: path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"