From 9755b0fb6256c5571f359ab66f3c92f4ff51d2f8 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 24 Jul 2024 14:00:45 +0100 Subject: [PATCH] section 5 v2 initial Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.1.x.yml | 645 +++++++++++++++++++++++------- tasks/section_5/cis_5.2.x.yml | 512 +++++++----------------- tasks/section_5/cis_5.3.1.x.yml | 55 +++ tasks/section_5/cis_5.3.2.x.yml | 200 +++++++++ tasks/section_5/cis_5.3.3.1.x.yml | 86 ++++ tasks/section_5/cis_5.3.3.2.x.yml | 204 ++++++++++ tasks/section_5/cis_5.3.3.3.x.yml | 79 ++++ tasks/section_5/cis_5.3.3.4.x.yml | 104 +++++ tasks/section_5/main.yml | 56 +-- 9 files changed, 1404 insertions(+), 537 deletions(-) create mode 100644 tasks/section_5/cis_5.3.1.x.yml create mode 100644 tasks/section_5/cis_5.3.2.x.yml create mode 100644 tasks/section_5/cis_5.3.3.1.x.yml create mode 100644 tasks/section_5/cis_5.3.3.2.x.yml create mode 100644 tasks/section_5/cis_5.3.3.3.x.yml create mode 100644 tasks/section_5/cis_5.3.3.4.x.yml diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index ce8bb58..0b4c63f 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -1,163 +1,518 @@ --- -- name: "5.1.1 | PATCH | Ensure cron daemon is enabled" - ansible.builtin.service: - name: crond - enabled: true +- name: "5.1.1 | PATCH | Ensure permissions on /etc/ssh/sshd_config are configured" when: - - rhel9cis_rule_5_1_1 + - rhel9cis_rule_5_1_1 tags: - - level1-server - - level1-workstation - - patch - - cron - - rule_5.1.1 - -- name: "5.1.2 | PATCH | Ensure permissions on /etc/crontab are configured" + - level1-server + - level1-workstation + - patch + - ssh + - permissions + - rule_5.1.1 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 ansible.builtin.file: - path: /etc/crontab - owner: root - group: root - mode: '0600' - when: - - rhel9cis_rule_5_1_2 - tags: - - level1-server - - level1-workstation - - patch - - cron - - rule_5.1.2 + path: "/etc/ssh/sshd_config" + owner: root + group: root + mode: '0600' -- 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' +- name: "5.1.2 | PATCH | Ensure permissions on SSH private host key files are configured" when: - - rhel9cis_rule_5_1_3 + - rhel9cis_rule_5_1_2 tags: - - level1-server - - level1-workstation - - 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: - - rhel9cis_rule_5_1_4 - tags: - - level1-server - - level1-workstation - - 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: - - rhel9cis_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: - - rhel9cis_rule_5_1_6 - tags: - - level1-server - - level1-workstation - - 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: - - rhel9cis_rule_5_1_7 - tags: - - level1-server - - level1-workstation - - patch - - cron - - rule_5.1.7 - -- name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users" + - level1-server + - level1-workstation + - patch + - ssh + - permissions + - rule_5.1.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 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.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: rhel9cis_5_1_2_ssh_private_host_key - - 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: rhel9cis_5_1_8_cron_allow_state + - name: "5.1.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: 'u-x,go-rwx' + loop: "{{ rhel9cis_5_1_2_ssh_private_host_key.files }}" + loop_control: + label: "{{ item.path }}" - - 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 rhel9cis_5_1_8_cron_allow_state.stat.exists else "touch" }}' - owner: root - group: root - mode: '0600' +- name: "5.1.3 | PATCH | Ensure permissions on SSH public host key files are configured" when: - - rhel9cis_rule_5_1_8 + - rhel9cis_rule_5_1_3 tags: - - level1-server - - level1-workstation - - patch - - cron - - rule_5.1.8 - -- name: "5.1.9 | PATCH | Ensure at is restricted to authorized users" + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 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.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: rhel9cis_5_1_3_ssh_public_host_key - - 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: rhel9cis_5_1_9_at_allow_state + - name: "5.1.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: 'u-x,go-wx' + loop: "{{ rhel9cis_5_1_3_ssh_public_host_key.files }}" + loop_control: + label: "{{ item.path }}" - - 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 rhel9cis_5_1_9_at_allow_state.stat.exists else "touch" }}' - owner: root - group: root - mode: '0600' +- name: "5.1.4 | PATCH | Ensure sshd Ciphers are configured" when: - - rhel9cis_rule_5_1_9 + - rhel9cis_rule_5_1_4 + - "'NO-SSHWEAKCIPHERS' not in rhel9cis_crypto_policy_module" tags: - - level1-server - - level1-workstation - - patch - - cron - - rule_5.1.9 + - level1-server + - level1-workstation + - automated + - patch + - crypto + - rule_5.1.4 + - NIST800-53R5_SC-8 + block: + - name: "5.1.4 | PATCH | Ensure sshd Ciphers are configured | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "5.1.4 | PATCH | Ensure sshd Ciphers are configured | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHWEAKCIPHERS' }}" + +- name: "5.1.5 | PATCH | Ensure sshd KexAlgorithms is configured" + when: + - rhel9cis_rule_5_1_5 + - "'NO-SHA1' not in rhel9cis_crypto_policy_module" + tags: + - level1-server + - level1-workstation + - automated + - patch + - crypto + - rule_5.1.5 + - NIST800-53R5_SC-6 + block: + - name: "5.1.5 | PATCH | Ensure sshd KexAlgorithms is configured | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SHA1.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "5.1.5 | PATCH | Ensure sshd KexAlgorithms is configured | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SHA1' }}" + +- name: "5.1.6 | PATCH | Ensure sshd KexAlgorithms is configured" + when: + - rhel9cis_rule_5_1_6 + - "'NO-SSHWEAKMACS' not in rhel9cis_crypto_policy_module" + tags: + - level1-server + - level1-workstation + - automated + - patch + - crypto + - rule_5.1.6 + - NIST800-53R5_SC-6 + block: + - name: "5.1.6 | PATCH | Ensure sshd KexAlgorithms is configured | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-SSHWEAKMACS.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SSHWEAKMACS.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "5.1.6 | PATCH | Ensure sshd KexAlgorithms is configured | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SHA1' }}" + +- name: "5.1.7 | PATCH | Ensure sshd access is configured" + when: + - rhel9cis_rule_5_1_7 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.7 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + block: + - name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for allowusers" + when: "rhel9cis_sshd_allowusers | length > 0" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: "^AllowUsers" + line: "AllowUsers {{ rhel9cis_sshd_allowusers }}" + validate: sshd -t -f %s + notify: Restart sshd + + - name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for allowgroups" + when: "rhel9cis_sshd_allowgroups | length > 0" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: "^AllowGroups" + line: "AllowGroups {{ rhel9cis_sshd_allowgroups }}" + validate: sshd -t -f %s + notify: Restart sshd + + - name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for denyusers" + when: "rhel9cis_sshd_denyusers'|default('') | length > 0" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: "^DenyUsers" + line: "DenyUsers {{ rhel9cis_sshd_denyusers }}" + validate: sshd -t -f %s + notify: Restart sshd + + - name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for denygroups" + when: "rhel9cis_sshd_denygroups|default('') | length > 0" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: "^DenyGroups" + line: "DenyGroups {{ rhel9cis_sshd_denygroups }}" + validate: sshd -t -f %s + notify: Restart sshd + +- name: "5.1.8 | PATCH | Ensure sshd Banner is configured" + when: + - rhel9cis_rule_5_1_8 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.8 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: '^Banner' + line: 'Banner /etc/issue.net' + +- name: "5.1.9 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured" + when: + - rhel9cis_rule_5_1_9 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.9 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "5.1.9 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured | Add line in sshd_config for ClientAliveInterval" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: '^ClientAliveInterval' + line: "ClientAliveInterval {{ rhel9cis_sshd_clientaliveinterval }}" + validate: sshd -t -f %s + + - name: "5.1.9 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured | Ensure SSH ClientAliveCountMax set to <= 3" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: '^ClientAliveCountMax' + line: "ClientAliveCountMax {{ rhel9cis_sshd_clientalivecountmax }}" + validate: sshd -t -f %s + +- name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled" + when: + - rhel9cis_rule_5_1_10 + tags: + - level2-server + - level1-workstation + - patch + - ssh + - rule_5.1.10 + - NIST800-53R5_CM-7 + block: + - name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled | config file" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(#|)\s*DisableForwarding + line: 'DisableForwarding yes' + validate: sshd -t -f %s + + - name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled | override" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config.d/50-redhat.conf + regexp: ^(?i)(#|)\s*X11Forwarding + line: 'X11Forwarding {{ rhel9cis_sshd_x11forwarding }}' + validate: sshd -t -f %s + +- name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled" + when: + - rhel9cis_rule_5_1_11 + tags: + - level1-server + - level1-workstation + - patch + - sshs + - rule_5.1.11 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*GSSAPIAuthentication + line: 'GSSAPIAuthentication no' + validate: sshd -t -f %s + +- name: "5.1.12 | PATCH | Ensure sshd HostbasedAuthentication is disabled" + when: + - rhel9cis_rule_5_1_12 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.12 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*HostbasedAuthentication + line: 'HostbasedAuthentication no' + validate: sshd -t -f %s + +- name: "5.1.13 | PATCH | Ensure sshd IgnoreRhosts is enabled" + when: + - rhel9cis_rule_5_1_13 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.13 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*IgnoreRhosts + line: 'IgnoreRhosts yes' + validate: sshd -t -f %s + +- name: "5.1.14 | PATCH | Ensure sshd LoginGraceTime is set to one minute or less" + when: + - rhel9cis_rule_5_1_14 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.14 + - NIST800-53R5_CM-6 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*LoginGraceTime + line: "LoginGraceTime {{ rhel9cis_sshd_logingracetime }}" + validate: sshd -t -f %s + +- name: "5.1.15 | PATCH | Ensure sshd LogLevel is appropriate" + when: + - rhel9cis_rule_5_1_15 + tags: + - level1-server + - level1-workstation + - patch + - sshs + - rule_5.1.15 + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*LogLevel + line: 'LogLevel {{ rhel9cis_ssh_loglevel }}' + validate: sshd -t -f %s + +- name: "5.1.16 | PATCH | Ensure sshd MaxAuthTries is set to 4 or less" + when: + - rhel9cis_rule_5_1_16 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.16 + - NIST800-53R5_AU-3 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: '^(#)?MaxAuthTries \d' + line: 'MaxAuthTries {{ rhel9cis_ssh_maxauthtries }}' + validate: sshd -t -f %s + +- name: "5.1.17 | PATCH | Ensure sshd MaxStartups is configured" + when: + - rhel9cis_rule_5_1_17 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.17 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*MaxStartups + line: 'MaxStartups {{ rhel9cis_ssh_maxstartups }}' + validate: sshd -t -f %s + +- name: "5.1.18 | PATCH | Ensure SSH MaxSessions is set to 10 or less" + when: + - rhel9cis_rule_5_1_18 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.18 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*MaxSessions + line: 'MaxSessions {{ rhel9cis_ssh_maxsessions }}' + validate: sshd -t -f %s + +- name: "5.1.19 | PATCH | Ensure sshd PermitEmptyPasswords is disabled" + when: + - rhel9cis_rule_5_1_19 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.19 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*PermitEmptyPasswords + line: 'PermitEmptyPasswords no' + validate: sshd -t -f %s + +- name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled" + when: + - rhel9cis_rule_5_1_20 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.20 + - NIST800-53R5_AC-6 + block: + - name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled | config file" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*PermitRootLogin + line: 'PermitRootLogin no' + validate: sshd -t -f %s + + - name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled | override file" + ansible.builtin.file: + path: /etc/ssh/sshd_config.d/01-permitrootlogin.conf + state: absent + +- name: "5.1.21 | PATCH | Ensure sshd PermitUserEnvironment is disabled" + when: + - rhel9cis_rule_5_1_21 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.21 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: "^#PermitUserEnvironment|^PermitUserEnvironment" + line: 'PermitUserEnvironment no' + validate: sshd -t -f %s + +- name: "5.1.22 | PATCH | Ensure SSH PAM is enabled" + when: + - rhel9cis_rule_5_1_22 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.22 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*MaxStartupsUsePAM + line: 'UsePAM yes' + validate: sshd -t -f %s diff --git a/tasks/section_5/cis_5.2.x.yml b/tasks/section_5/cis_5.2.x.yml index ac62767..6bb0608 100644 --- a/tasks/section_5/cis_5.2.x.yml +++ b/tasks/section_5/cis_5.2.x.yml @@ -1,391 +1,165 @@ --- -- name: "5.2.1 | PATCH | Ensure permissions on /etc/ssh/sshd_config are configured" - ansible.builtin.file: - path: "/etc/ssh/sshd_config" - owner: root - group: root - mode: '0600' +- name: "5.2.1 | PATCH | Ensure sudo is installed" when: - - rhel9cis_rule_5_2_1 + - rhel9cis_rule_5_2_1 tags: - - level1-server - - level1-workstation - - patch - - ssh - - permissions - - rule_5.2.1 + - level1-server + - level1-workstation + - patch + - sudo + - rule_5.2.1 + - NIST800-53R5_AC-6 + ansible.builtin.package: + name: sudo + state: present -- name: "5.2.2 | PATCH | Ensure permissions on SSH private host key files are configured" +- name: "5.2.2 | PATCH | Ensure sudo commands use pty" + when: + - rhel9cis_rule_5_2_2 + tags: + - level1-server + - level1-workstation + - patch + - sudo + - rule_5.2.2 + - NIST800-53R5_AC-6 + ansible.builtin.lineinfile: + path: /etc/sudoers + line: "Defaults use_pty" + validate: '/usr/sbin/visudo -cf %s' + +- name: "5.2.3 | PATCH | Ensure sudo log file exists" + when: + - rhel9cis_rule_5_2_3 + tags: + - level1-server + - level1-workstation + - patch + - sudo + - rule_5.2.3 + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + ansible.builtin.lineinfile: + path: /etc/sudoers + regexp: '^Defaults logfile=' + line: 'Defaults logfile="{{ rhel9cis_sudolog_location }}"' + validate: '/usr/sbin/visudo -cf %s' + +- name: "5.2.4 | PATCH | Ensure users must provide password for escalation" + when: + - rhel9cis_rule_5_2_4 + tags: + - level2-server + - level2-workstation + - patch + - sudo + - rule_5.2.4 + - NIST800-53R5_AC-6 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: rhel9cis_5_2_2_ssh_private_host_key + - name: "5.2.4 | AUDIT | Ensure users must provide password for escalation | discover accts with NOPASSWD" + ansible.builtin.shell: grep -Ei '(nopasswd)' /etc/sudoers /etc/sudoers.d/* | cut -d':' -f1 + become: true + changed_when: false + failed_when: false + register: rhel9cis_5_2_4_nopasswd - - 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' - loop: "{{ rhel9cis_5_2_2_ssh_private_host_key.files }}" - loop_control: - label: "{{ item.path }}" + - name: "5.2.4 | PATCH | Ensure users must provide password for escalation" + when: rhel9cis_5_2_4_nopasswd.std | length > 0 + ansible.builtin.replace: + path: "{{ item }}" + regexp: '^((?!#|{% for name in rhel9cis_sudoers_exclude_nopasswd_list %}{{ name }}{% if not loop.last -%}|{%- endif -%}{% endfor %}).*)NOPASSWD(.*)' + replace: '\1PASSWD\2' + validate: '/usr/sbin/visudo -cf %s' + loop: "{{ rhel9cis_5_2_4_nopasswd.stdout_lines }}" + +- name: "5.2.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally" when: - - rhel9cis_rule_5_2_2 + - rhel9cis_rule_5_2_5 tags: - - level1-server - - level1-workstation - - patch - - ssh - - permissions - - rule_5.2.2 - -- name: "5.2.3 | PATCH | Ensure permissions on SSH public host key files are configured" + - level1-server + - level1-workstation + - patch + - sudo + - rule_5.2.5 + - NIST800-53R5_AC-6 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: rhel9cis_5_2_3_ssh_public_host_key + - name: "5.2.5 | AUDIT | Ensure re-authentication for privilege escalation is not disabled globally" + ansible.builtin.shell: grep -Ei '(!authenticate)' /etc/sudoers /etc/sudoers.d/* | cut -d':' -f1 + become: true + changed_when: false + failed_when: false + register: rhel9cis_5_2_4_authenticate - - 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' - loop: "{{ rhel9cis_5_2_3_ssh_public_host_key.files }}" - loop_control: - label: "{{ item.path }}" + - name: "5.2.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally" + when: rhel9cis_5_2_4_authenticate.stdout | length > 0 + ansible.builtin.replace: + path: "{{ item }}" + regexp: '^([^#].*)!authenticate(.*)' + replace: '\1authenticate\2' + validate: '/usr/sbin/visudo -cf %s' + loop: "{{ rhel9cis_5_2_4_authenticate.stdout_lines }}" + +- name: "5.2.6 | PATCH | Ensure sudo authentication timeout is configured correctly" when: - - rhel9cis_rule_5_2_3 + - rhel9cis_rule_5_2_6 tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.3 - -- name: "5.2.4 | PATCH | Ensure SSH access is limited" + - level1-server + - level1-workstation + - patch + - sudo + - rule_5.2.6 block: - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for allowusers" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^AllowUsers" - line: "AllowUsers {{ rhel9cis_sshd['allowusers'] }}" - validate: sshd -t -f %s - notify: Restart sshd - when: "rhel9cis_sshd['allowusers']|default('') | length > 0" + - name: "5.2.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: rhel9cis_5_2_6_timeout_files - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for allowgroups" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^AllowGroups" - line: "AllowGroups {{ rhel9cis_sshd['allowgroups'] }}" - validate: sshd -t -f %s - notify: Restart sshd - when: "rhel9cis_sshd['allowgroups']|default('') | length > 0" + - name: "5.2.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={{ rhel9cis_sudo_timestamp_timeout }}" + validate: '/usr/sbin/visudo -cf %s' + when: rhel9cis_5_2_6_timeout_files.stdout | length == 0 - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for denyusers" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^DenyUsers" - line: "DenyUsers {{ rhel9cis_sshd['denyusers'] }}" - validate: sshd -t -f %s - notify: Restart sshd - when: "rhel9cis_sshd['denyusers']|default('') | length > 0" + - name: "5.2.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={{ rhel9cis_sudo_timestamp_timeout }}" + validate: '/usr/sbin/visudo -cf %s' + loop: "{{ rhel9cis_5_2_6_timeout_files.stdout_lines }}" + when: rhel9cis_5_2_6_timeout_files.stdout | length > 0 - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for denygroups" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^DenyGroups" - line: "DenyGroups {{ rhel9cis_sshd['denygroups'] }}" - validate: sshd -t -f %s - notify: Restart sshd - when: "rhel9cis_sshd['denygroups']|default('') | length > 0" +- name: "5.2.7 | PATCH | Ensure access to the su command is restricted" when: - - rhel9cis_rule_5_2_4 + - rhel9cis_rule_5_2_7 tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.4 - -- name: "5.2.5 | PATCH | Ensure SSH LogLevel is appropriate" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#LogLevel|^LogLevel" - line: 'LogLevel {{ rhel9cis_ssh_loglevel }}' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_5 - tags: - - level1-server - - level1-workstation - - patch - - sshs - - rule_5.2.5 - -- name: "5.2.6 | PATCH | Ensure SSH PAM is enabled" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#UsePAM|^UsePAM" - line: 'UsePAM yes' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_6 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.6 - -- name: "5.2.7 | PATCH | Ensure SSH root login is disabled" + - level1-server + - level1-workstation + - patch + - sudo + - rule_5.2.7 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 block: - - name: "5.2.7 | PATCH | Ensure SSH root login is disabled | config file" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#PermitRootLogin|^PermitRootLogin" - line: 'PermitRootLogin no' - validate: sshd -t -f %s + - name: "5.2.7 | PATCH | Ensure access to the su command is restricted | Ensure sugroup exists" + ansible.builtin.group: + name: "{{ rhel9cis_sugroup }}" + state: present + register: rhel9cis_5_2_7_sugroup - - name: "5.2.7 | PATCH | Ensure SSH root login is disabled | override file" - ansible.builtin.file: - path: /etc/ssh/sshd_config.d/01-permitrootlogin.conf - state: absent - when: - - rhel9cis_rule_5_2_7 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.7 + - name: "5.2.7 | PATCH | Ensure access to the su command is restricted | remove users from group" + ansible.builtin.lineinfile: + path: /etc/group + regexp: '^{{ rhel9cis_sugroup }}(:.:.*:).*$' + line: '{{ rhel9cis_sugroup }}\g<1>' + backrefs: true -- name: "5.2.8 | PATCH | Ensure SSH HostbasedAuthentication is disabled" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#HostbasedAuthentication|^HostbasedAuthentication" - line: 'HostbasedAuthentication no' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_8 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.8 - -- name: "5.2.9 | PATCH | Ensure SSH PermitEmptyPasswords is disabled" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#PermitEmptyPasswords|^PermitEmptyPasswords" - line: 'PermitEmptyPasswords no' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_9 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.9 - -- name: "5.2.10 | PATCH | Ensure SSH PermitUserEnvironment is disabled" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#PermitUserEnvironment|^PermitUserEnvironment" - line: 'PermitUserEnvironment no' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_10 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.10 - -- name: "5.2.11 | PATCH | Ensure SSH IgnoreRhosts is enabled" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#IgnoreRhosts|^IgnoreRhosts" - line: 'IgnoreRhosts yes' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_11 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.11 - -- name: "5.2.12 | PATCH | Ensure SSH X11 forwarding is disabled" - block: - - - name: "5.2.12 | PATCH | Ensure SSH X11 forwarding is disabled | config file" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#X11Forwarding|^X11Forwarding" - line: 'X11Forwarding no' - validate: sshd -t -f %s - - - name: "5.2.12 | PATCH | Ensure SSH X11 forwarding is disabled | override" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config.d/50-redhat.conf - regexp: "^#X11Forwarding|^X11Forwarding" - line: 'X11Forwarding no' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_12 - tags: - - level2-server - - level1-workstation - - patch - - ssh - - rule_5.2.12 - -- name: "5.2.13 | PATCH | Ensure SSH AllowTcpForwarding is disabled" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#AllowTcpForwarding|^AllowTcpForwarding" - line: 'AllowTcpForwarding no' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_13 - tags: - - level2-server - - level2-workstation - - 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 - changed_when: false - failed_when: ( ssh_crypto_discovery.rc not in [ 0, 1 ] ) - register: ssh_crypto_discovery - - - 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: ssh_crypto_discovery.stdout | length > 0 - when: - - rhel9cis_rule_5_2_14 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.14 - -- name: "5.2.15 | PATCH | Ensure SSH warning banner is configured" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: '^Banner' - line: 'Banner /etc/issue.net' - when: - - rhel9cis_rule_5_2_15 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.15 - -- name: "5.2.16 | PATCH | Ensure SSH MaxAuthTries is set to 4 or less" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: '^(#)?MaxAuthTries \d' - line: 'MaxAuthTries 4' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_16 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.16 - -- name: "5.2.17 | PATCH | Ensure SSH MaxStartups is configured" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#MaxStartups|^MaxStartups" - line: 'MaxStartups 10:30:60' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_17 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.17 - -- name: "5.2.18 | PATCH | Ensure SSH MaxSessions is set to 10 or less" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#MaxSessions|^MaxSessions" - line: 'MaxSessions {{ rhel9cis_ssh_maxsessions }}' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_18 - tags: - - level1-server - - level1-workstation - - 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: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#LoginGraceTime|^LoginGraceTime" - line: "LoginGraceTime {{ rhel9cis_sshd['logingracetime'] }}" - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_19 - tags: - - level1-server - - level1-workstation - - 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: "{{ rhel9_cis_sshd_config_file }}" - regexp: '^ClientAliveInterval' - line: "ClientAliveInterval {{ rhel9cis_sshd['clientaliveinterval'] }}" - validate: sshd -t -f %s - - - name: "5.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured | Ensure SSH ClientAliveCountMax set to <= 3" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: '^ClientAliveCountMax' - line: "ClientAliveCountMax {{ rhel9cis_sshd['clientalivecountmax'] }}" - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_20 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.20 + - name: "5.2.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={{ rhel9cis_sugroup }}' diff --git a/tasks/section_5/cis_5.3.1.x.yml b/tasks/section_5/cis_5.3.1.x.yml new file mode 100644 index 0000000..050a081 --- /dev/null +++ b/tasks/section_5/cis_5.3.1.x.yml @@ -0,0 +1,55 @@ +--- + +- name: "5.3.1.1 | PATCH | Ensure latest version of pam is installed" + when: + - rhel9cis_rule_5_3_1_1 + - ansible_facts.packages['pam'][0]['version'] is version('1.5.1-19', '<') or + "'pam' not in ansible_facts.packages" + tags: + - level1-server + - level1-workstation + - patch + - pam + - rule_5.3.1.1 + ansible.builtin.package: + name: pam + state: latest + +- name: "5.3.1.2 | PATCH | Ensure latest version of authselect is installed" + when: + - rhel9cis_rule_5_3_1_2 + - rhel9cis_authselect_pkg_update + - ansible_facts.packages['authselect'][0]['version'] is version('1.2.6-2', '<') or + "'authselect' not in ansible_facts.packages" + tags: + - level1-server + - level1-workstation + - patch + - pam + - rule_5.3.1.2 + block: + - name: "5.3.1.2 | PATCH | Ensure latest version of authselect is installed | Patch" + ansible.builtin.package: + name: authselect + state: latest + register: rhel9cis_authselect_update + + - name: "5.3.1.2 | AUDIT | Ensure latest version of authselect is installed | Patch" + when: rhel9cis_authselect_update.changed # noqa no-handler + ansible.builtin.set_fact: + authselect_update: OK + +- name: "5.3.1.3 | PATCH | Ensure libpwquality is installed" + when: + - rhel9cis_rule_5_3_1_3 + - ansible_facts.packages['libpwquality'][0]['version'] is version('1.4.4-8', '<') + "'libpwquality' not in ansible_facts.packages" + tags: + - level1-server + - level1-workstation + - patch + - pam + - rule_5.3.1.3 + ansible.builtin.package: + name: libpwquality + state: latest diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml new file mode 100644 index 0000000..3f318c9 --- /dev/null +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -0,0 +1,200 @@ +--- + +- name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules" + when: + - rhel9cis_rule_5_3_2_1 + - rhel9cis_disruption_high + - rhel9cis_allow_authselect_updates + tags: + - level1-server + - level1-workstation + - manual + - patch + - authselect + - 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'] }}" + args: + 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.2 | PATCH | Ensure pam_faillock module is enabled" + when: + - rhel9cis_rule_5_3_2_2 + - rhel9cis_disruption_high + - rhel9cis_allow_authselect_updates + 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_5.3.2.2 + notify: Update_authselect + 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 + + - 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" + +- 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 | 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 + + - 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]' } + +- name: "5.3.2.4 | PATCH | Ensure pam_pwhistory module is enabled" + when: + - rhel9cis_rule_5_3_2_4 + - rhel9cis_disruption_high + - rhel9cis_allow_authselect_updates + tags: + - level1-server + - level1-workstation + - automated + - patch + - 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 + + - 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" + +- name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled" + when: + - rhel9cis_rule_5_3_2_5 + - rhel9cis_disruption_high + - rhel9cis_allow_authselect_updates + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - authselect + - rule_5.3.2.5 + block: + - name: "5.3.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: rhel9cis_authselect_pam_unix.rc not in [ 0, 1 ] + register: 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: + path: /etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + backrefs: true + insertafter: "{{ item.after | default (omit) }}" + insertbefore: "{{ item.before | default (omit) }}" + 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: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled | password-auth" + when: "'password-auth:password' not in rhel9cis_authselect_pam_unix.stdout" + ansible.builtin.lineinfile: + path: /etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth + line: "{{ item.line }}" + regexp: "{{ item.regexp }}" + backrefs: true + insertafter: "{{ item.after | default (omit) }}" + insertbefore: "{{ item.before | default (omit) }}" + 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_5/cis_5.3.3.1.x.yml b/tasks/section_5/cis_5.3.3.1.x.yml new file mode 100644 index 0000000..67b8763 --- /dev/null +++ b/tasks/section_5/cis_5.3.3.1.x.yml @@ -0,0 +1,86 @@ +--- + +- name: "5.3.3.1.1 | PATCH | Ensure password failed attempts lockout is configured" + when: + - rhel8cis_rule_5_3_3_1_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_5.3.3.1.1 + block: + - name: "5.3.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: "5.3.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: "5.3.3.1.2 | PATCH | Ensure password unlock time is configured" + when: + - rhel8cis_rule_5_3_3_1_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_5.3.3.1.2 + block: + - name: "5.3.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: "5.3.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: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account" + when: + - rhel9cis_rule_5_3_3_1_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_5.3.3.1.3 + block: + - name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | configure faillock.conf" + ansible.builtin.lineinfile: + path: /etc/security/faillock.conf + regexp: '^{{ rhel9cis_pamroot_lock_option }}' + line: "{{ rhel9cis_pamroot_lock_string }}" + insertafter: '^# end of pam-auth-update config' + create: true + + - name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | pam_files" + when: not rhel9cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s(even_deny_root|root_unlock_time=\d*)"(\s*=\s*\d|.*)\S+(.*$) + replace: \1\2\4 + loop: + - password + - system diff --git a/tasks/section_5/cis_5.3.3.2.x.yml b/tasks/section_5/cis_5.3.3.2.x.yml new file mode 100644 index 0000000..931f867 --- /dev/null +++ b/tasks/section_5/cis_5.3.3.2.x.yml @@ -0,0 +1,204 @@ +--- + +- name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured" + when: + - rhel9cis_rule_5_3_3_2_1 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.2.1 + - NIST800-53R5_IA-5 + - pam + block: + - name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Remove difok from conf files except expected file" + when: + - item != rhel9cis_passwd_difok_file + ansible.builtin.replace: + path: "{{ item }}" + regexp: 'difok\s*=\s*\d+\b' + replace: '' + with_fileglob: + - '/etc/security/pwquality.conf' + - '/etc/security/pwquality.conf.d/*.conf' + - /etc/pam.d/*-auth + + - name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Ensure difok file exists" + ansible.builtin.template: + src: "{{ rhel9cis_passwd_difok_file }}.j2" + dest: "/{{ rhel9cis_passwd_difok_file }}" + owner: root + group: root + mode: '0600' + +- name: "5.3.3.2.2 | PATCH | Ensure password length is configured" + when: + - rhel9cis_rule_5_3_3_2_2 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.2.2 + - NIST800-53R5_IA-5 + - pam + block: + - name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Remove minlen from conf files except expected file" + when: + - item != rhel9cis_passwd_minlen_file + ansible.builtin.replace: + path: "{{ item }}" + regexp: 'minlen\s*=\s*\d+\b' + replace: '' + with_fileglob: + - '/etc/security/pwquality.conf' + - '/etc/security/pwquality.conf.d/*.conf' + - '/etc/pam.d/*-auth' + + - name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Ensure minlen file exists" + ansible.builtin.template: + src: "{{ rhel9cis_passwd_minlen_file }}.j2" + dest: "/{{ rhel9cis_passwd_minlen_file }}" + owner: root + group: root + mode: '0600' + +- name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured" + when: + - rhel9cis_rule_5_3_3_2_3 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.2.3 + - NIST800-53R5_IA-5 + - pam + block: + - name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Remove pwd complex settings from conf files except expected file" + when: + - item != rhel9cis_passwd_complex_file + ansible.builtin.replace: + path: "{{ item }}" + regexp: '(minclass|[dulo]credit)\s*=\s*(-\d|\d+)\b' + replace: '' + with_fileglob: + - '/etc/security/pwquality.conf' + - '/etc/security/pwquality.conf.d/*.conf' + - '/etc/pam.d/*-auth' + + - name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Ensure complexity file exists" + ansible.builtin.template: + src: "{{ rhel9cis_passwd_complex_file }}.j2" + dest: "/{{ rhel9cis_passwd_complex_file }}" + owner: root + group: root + mode: '0600' + +- name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured" + when: + - rhel9cis_rule_5_3_3_2_4 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.2.4 + - NIST800-53R5_IA-5 + - pam + block: + - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Remove maxrepeat settings from conf files except expected file" + when: + - item != rhel9cis_passwd_maxrepeat_file + ansible.builtin.replace: + path: "{{ item }}" + regexp: 'maxrepeat\s*=\s*\d+\b' + replace: '' + with_fileglob: + - '/etc/security/pwquality.conf' + - '/etc/security/pwquality.conf.d/*.conf' + - '/etc/pam.d/*-auth' + + - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Ensure maxrepeat file exists" + ansible.builtin.template: + src: "{{ rhel9cis_passwd_maxrepeat_file }}.j2" + dest: "/{{ rhel9cis_passwd_maxrepeat_file }}" + owner: root + group: root + mode: '0600' + +- name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is is configured" + when: + - rhel9cis_rule_5_3_3_2_5 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.2.5 + - NIST800-53R5_IA-5 + - pam + block: + - name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Remove maxsequence settings from conf files except expected file" + when: + - item != rhel9cis_passwd_maxsequence_file + ansible.builtin.replace: + path: "{{ item }}" + regexp: 'maxsequence\s*=\s*\d+\b' + replace: '' + with_fileglob: + - '/etc/security/pwquality.conf' + - '/etc/security/pwquality.conf.d/*.conf' + - '/etc/pam.d/*-auth' + + - name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Ensure maxsequence file exists" + ansible.builtin.template: + src: "{{ rhel9cis_passwd_maxsequence_file }}.j2" + dest: "/{{ rhel9cis_passwd_maxsequence_file }}" + owner: root + group: root + mode: '0600' + +- name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled" + when: + - rhel9cis_rule_5_3_3_2_6 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.2.6 + - NIST800-53R5_IA-5 + - pam + block: + - name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Remove dictcheck settings from conf files except expected file" + when: + - item != rhel9cis_passwd_dictcheck_file + ansible.builtin.replace: + path: "{{ item }}" + regexp: 'dictcheck\s*=\s*\d+\b' + replace: '' + with_fileglob: + - '/etc/security/pwquality.conf' + - '/etc/security/pwquality.conf.d/*.conf' + - '/etc/pam.d/*-auth' + + - name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Ensure dictcheck file exists" + ansible.builtin.template: + src: "{{ rhel9cis_passwd_dictcheck_file }}.j2" + dest: "/{{ rhel9cis_passwd_dictcheck_file }}" + owner: root + group: root + mode: '0600' + +- name: "5.3.3.2.7 | PATCH | Ensure password quality is enforced for the root user" + when: + - rhel9cis_rule_5_3_3_2_7 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.2.7 + - NIST800-53R5_IA-5 + - pam + ansible.builtin.template: + src: "{{ rhel9cis_passwd_quality_enforce_root_file }}.j2" + dest: "/{{ rhel9cis_passwd_quality_enforce_root_file }}" + owner: root + group: root + mode: '0600' diff --git a/tasks/section_5/cis_5.3.3.3.x.yml b/tasks/section_5/cis_5.3.3.3.x.yml new file mode 100644 index 0000000..659ea82 --- /dev/null +++ b/tasks/section_5/cis_5.3.3.3.x.yml @@ -0,0 +1,79 @@ +--- + +- name: "5.3.3.3.1 | PATCH | Ensure password history remember is configured" + when: + - rhel9cis_rule_5_3_3_3_1 + - rhel9cis_disruption_high + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.3.1 + - pam + block: + - name: "5.3.3.3.1 | AUDIT | Ensure password history remember is configured | Check existing files" + ansible.builtin.shell: grep -Psi -- '^\h*password\s+[^#\n\r]+\h+pam_pwhistory\.so\s+([^#\n\r]+\s+)?remember=\d+\b' /etc/pam.d/password-auth /etc/pam.d/system-auth + register: rhel9_pwhistory_remember + 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 + 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 + +- 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 + - patch + - rule_5.3.3.3.2 + - pam + block: + - name: "5.3.3.3.2 | AUDIT | Ensure password history is enforced for the root user | Check existing files" + ansible.builtin.shell: grep -Psi -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?enforce_for_root\b' /etc/pam.d/common-password + register: rhel9_pwhistory_enforce_for_root + 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" + when: rhel9_pwhistory_enforce_for_root.stdout | length > 0 + 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.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 + - pam + block: + - name: "5.3.3.3.3 | AUDIT | Ensure pam_pwhistory includes use_authtok | Check existing files" + ansible.builtin.shell: grep -Psi -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?use_authtok\b' /etc/pam.d/common-password + register: rhel9_pwhistory_use_authtok + 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" + when: rhel9_pwhistory_use_authtok.stdout | length > 0 + 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' + backrefs: true + notify: Pam_auth_update_pwhistory diff --git a/tasks/section_5/cis_5.3.3.4.x.yml b/tasks/section_5/cis_5.3.3.4.x.yml new file mode 100644 index 0000000..4faedb3 --- /dev/null +++ b/tasks/section_5/cis_5.3.3.4.x.yml @@ -0,0 +1,104 @@ +--- + +- name: "5.3.3.4.1 | PATCH | Ensure pam_unix does not include nullok" + when: + - rhel9cis_rule_5_3_3_4_1 + - rhel9cis_disruption_high + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.4.1 + - pam + block: + - name: "5.3.3.4.1 | PATCH | Ensure pam_unix does not include nullok | capture state" + ansible.builtin.shell: grep -E "pam_unix.so.*nullok" /etc/pam.d/*-auth | cut -d ':' -f1 | uniq + changed_when: false + failed_when: rhel9cis_pam_nullok.rc not in [ 0, 1 ] + register: rhel9cis_pam_nullok + + - name: "5.3.3.4.1 | PATCH | Ensure pam_unix does not include nullok | Ensure nullok removed" + when: rhel9cis_pam_nullok.stdout | length > 0 + ansible.builtin.replace: + path: "{{ item }}" + regexp: nullok + replace: '' + loop: "{{ rhel9cis_pam_nullok.stdout_lines }}" + notify: Pam_auth_update_pwunix + +- name: "5.3.3.4.2 | PATCH | Ensure pam_unix does not include remember" + when: + - rhel9cis_rule_5_3_3_4_2 + tags: + - level1-server + - level1-workstation + - patch + - pam + - rule_5.3.3.4.2 + block: + - name: "5.3.3.4.2 | AUDIT | Ensure pam_unix does not include remember | capture state" + ansible.builtin.shell: grep -PH -- '^\h*^\h*[^#\n\r]+\h+pam_unix\.so\b' /etc/pam.d/common-{password,auth,account,session,session-noninteractive} | grep -Pv -- '\bremember=\d\b' + changed_when: false + failed_when: rhel9cis_pam_remember.rc not in [ 0, 1 ] + register: rhel9cis_pam_remember + + - name: "5.3.3.4.2 | PATCH | Ensure pam_unix does not include remember | Ensure remember removed" + when: rhel9cis_pam_remember.stdout | length > 0 + ansible.builtin.replace: + path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwunix_file }}" + regexp: remember=\d+ + replace: '' + notify: Pam_auth_update_pwunix + +- name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm" + when: + - rhel9cis_rule_5_3_3_4_3 + tags: + - level1-server + - level1-workstation + - patch + - pam + - rule_5.3.3.4.3 + - NIST800-53R5_IA-5 + block: + - name: "5.3.3.4.3 | AUDIT | Ensure pam_unix includes a strong password hashing algorithm | capture state" + ansible.builtin.shell: grep -PH -- '^\h*password\h+([^#\n\r]+)\h+pam_unix\.so\h+([^#\n\r]+\h+)?("{{ rhel9cis_passwd_hash_algo }}")\b' /etc/pam.d/*-auth + changed_when: false + failed_when: rhel9cis_pam_pwhash.rc not in [ 0, 1 ] + register: rhel9cis_pam_pwhash + + - name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | Ensure hash algorithm set" + when: rhel9cis_pam_remember.stdout | length > 0 + ansible.builtin.replace: + path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwunix_file }}" + regexp: "(md5|bigcrypt|sha256|blowfish|gost_yescrypt|sha512|yescrypt)" + replace: '{{ rhel9cis_passwd_hash_algo }}' + notify: Pam_auth_update_pwunix + +- name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok" + when: + - rhel9cis_rule_5_3_3_4_4 + tags: + - level1-server + - level1-workstation + - patch + - pam + - rule_5.3.3.4.4 + - NIST800-53R5_IA-5 + block: + - name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | capture state" + ansible.builtin.shell: grep -PH -- '^\h*password\h+([^#\n\r]+)\h+pam_unix\.so\h+([^#\n\r]+\h+)?use_authtok\b' /etc/pam.d/{password,system}-auth + changed_when: false + failed_when: rhel9cis_pam_authtok.rc not in [ 0, 1 ] + register: rhel9cis_pam_authtok + + - name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | pam_files" + when: + - rhel9cis_pam_authtok is defined + - rhel9cis_pam_authtok.stdout | length > 0 + ansible.builtin.lineinfile: + path: "{{ item }}" + regexp: ^(\s*password\s+[success=end.*]\s+pam_unix\.so)(.*)\s+use_authtok\s*=\s*\S+(.*$) + line: \1\2\3 use_authtok + backrefs: true + loop: "{{ rhel9cis_pam_authtok.stdout_lines }}" diff --git a/tasks/section_5/main.yml b/tasks/section_5/main.yml index be71ea5..ae908ac 100644 --- a/tasks/section_5/main.yml +++ b/tasks/section_5/main.yml @@ -2,38 +2,48 @@ # Access, Authentication, and Authorization -- name: "SECTION | 5.1 | Configure time-based job schedulers" - ansible.builtin.import_tasks: - file: cis_5.1.x.yml - -- name: "SECTION | 5.2 | Configure SSH Server" - ansible.builtin.import_tasks: - file: cis_5.2.x.yml +- name: "SECTION | 5.1 | Configure SSH Server" when: - - "'openssh-server' in ansible_facts.packages" - -- name: "SECTION | 5.3 | Configure privilege escalation" + - "'openssh-server' in ansible_facts.packages" ansible.builtin.import_tasks: - file: cis_5.3.x.yml + file: cis_5.1.x.yml -- name: "SECTION | 5.4 | Configure authselect" +- name: "SECTION | 5.2 | Configure privilege escalation" ansible.builtin.import_tasks: - file: cis_5.4.x.yml + file: cis_5.2.x.yml -- name: "SECTION | 5.5 | Configure PAM | not authselect" +- name: "SECTION | 5.3.1.x | Configure PAM software packages" ansible.builtin.import_tasks: - file: cis_5.5.x.yml - when: not rhel9cis_authselect_custom_profile_select + file: cis_5.3.1.x.yml -- name: "SECTION | 5.5 | Configure PAM | authselect" +- name: "SECTION | 5.3.2.x | Configure authselect" ansible.builtin.import_tasks: - file: cis_5.5.x_authselect.yml - when: rhel9cis_authselect_custom_profile_select + file: cis_5.3.2.x.yml -- name: "SECTION | 5.6.1.x | Shadow Password Suite Parameters" +- name: "SECTION | 5.3.3.1.x | Configure pam_faillock module" ansible.builtin.import_tasks: - file: cis_5.6.1.x.yml + file: cis_5.3.3.1.x.yml -- name: "SECTION | 5.6.x | Misc. User Account Settings" +- name: "SECTION | 5.3.3.2.x | Configure pam_pwquality module" ansible.builtin.import_tasks: - file: cis_5.6.x.yml + file: cis_5.3.3.2.x.yml + +- name: "SECTION | 5.3.3.3.x | Configure pam_pwhistory module" + ansible.builtin.import_tasks: + file: cis_5.3.3.3.x.yml + +- name: "SECTION | 5.3.3.4.x | Configure pam_unix module" + ansible.builtin.import_tasks: + file: cis_5.3.3.4.x.yml + +- name: "SECTION | 5.4.1.x | Configure shadow password suite parameters" + ansible.builtin.import_tasks: + file: cis_5.4.1.x.yml + +- name: "SECTION | 5.4.2.x | Configure root and system accounts and environment" + ansible.builtin.import_tasks: + file: cis_5.4.2.x.yml + +- name: "SECTION | 5.4.3.x | Configure user default environment" + ansible.builtin.import_tasks: + file: cis_5.4.3.x.yml