diff --git a/defaults/main.yml b/defaults/main.yml index 117933e..3ce2c46 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -28,11 +28,11 @@ os_check: true # E.g: If you want to execute the tasks of Section 1 you should set the "_section1" variable to true. # If you do not want the tasks from that section to get executed you simply set the variable to "false". rhel9cis_section1: true -rhel9cis_section2: true -rhel9cis_section3: true -rhel9cis_section4: true -rhel9cis_section5: true -rhel9cis_section6: true +rhel9cis_section2: false +rhel9cis_section3: false +rhel9cis_section4: false +rhel9cis_section5: false +rhel9cis_section6: false # This is used for audit purposes to run only specifc level use the tags # e.g. @@ -125,61 +125,98 @@ audit_log_dir: '/opt' # Section 1 is Initial setup (FileSystem Configuration, Configure Software Updates, Filesystem Integrity Checking, Secure Boot Settings, # Additional Process Hardening, Mandatory Access Control, Command Line Warning Banners, and GNOME Display Manager) +# Filesystem kernel modules rhel9cis_rule_1_1_1_1: true rhel9cis_rule_1_1_1_2: true -rhel9cis_rule_1_1_2_1: true -rhel9cis_rule_1_1_2_2: true -rhel9cis_rule_1_1_2_3: true -rhel9cis_rule_1_1_2_4: true -rhel9cis_rule_1_1_3_1: true -rhel9cis_rule_1_1_3_2: true -rhel9cis_rule_1_1_3_3: true -rhel9cis_rule_1_1_4_1: true -rhel9cis_rule_1_1_4_2: true -rhel9cis_rule_1_1_4_3: true -rhel9cis_rule_1_1_4_4: true -rhel9cis_rule_1_1_5_1: true -rhel9cis_rule_1_1_5_2: true -rhel9cis_rule_1_1_5_3: true -rhel9cis_rule_1_1_5_4: true -rhel9cis_rule_1_1_6_1: true -rhel9cis_rule_1_1_6_2: true -rhel9cis_rule_1_1_6_3: true -rhel9cis_rule_1_1_6_4: true -rhel9cis_rule_1_1_7_1: true -rhel9cis_rule_1_1_7_2: true -rhel9cis_rule_1_1_7_3: true -rhel9cis_rule_1_1_8_1: true -rhel9cis_rule_1_1_8_2: true -rhel9cis_rule_1_1_8_3: true -rhel9cis_rule_1_1_8_4: true -rhel9cis_rule_1_1_9: true -rhel9cis_rule_1_2_1: true -rhel9cis_rule_1_2_2: true -rhel9cis_rule_1_2_3: true -rhel9cis_rule_1_2_4: true -rhel9cis_rule_1_3_1: true -rhel9cis_rule_1_3_2: true -rhel9cis_rule_1_3_3: true +rhel9cis_rule_1_1_1_3: true +rhel9cis_rule_1_1_1_4: true +rhel9cis_rule_1_1_1_5: true +rhel9cis_rule_1_1_1_6: true +rhel9cis_rule_1_1_1_7: true +rhel9cis_rule_1_1_1_8: true +rhel9cis_rule_1_1_1_9: true +# Filesystems +# /tmp +rhel9cis_rule_1_1_2_1_1: true +rhel9cis_rule_1_1_2_1_2: true +rhel9cis_rule_1_1_2_1_3: true +rhel9cis_rule_1_1_2_1_4: true +# /dev/shm +rhel9cis_rule_1_1_2_2_1: true +rhel9cis_rule_1_1_2_2_2: true +rhel9cis_rule_1_1_2_2_3: true +rhel9cis_rule_1_1_2_2_4: true +# /home +rhel9cis_rule_1_1_2_3_1: true +rhel9cis_rule_1_1_2_3_2: true +rhel9cis_rule_1_1_2_3_3: true +# /var +rhel9cis_rule_1_1_2_4_1: true +rhel9cis_rule_1_1_2_4_2: true +rhel9cis_rule_1_1_2_4_3: true +# /var/tmp +rhel9cis_rule_1_1_2_5_1: true +rhel9cis_rule_1_1_2_5_2: true +rhel9cis_rule_1_1_2_5_3: true +rhel9cis_rule_1_1_2_5_4: true +# /var/log +rhel9cis_rule_1_1_2_6_1: true +rhel9cis_rule_1_1_2_6_2: true +rhel9cis_rule_1_1_2_6_3: true +rhel9cis_rule_1_1_2_6_4: true +# /var/log/audit +rhel9cis_rule_1_1_2_7_1: true +rhel9cis_rule_1_1_2_7_2: true +rhel9cis_rule_1_1_2_7_3: true +rhel9cis_rule_1_1_2_7_4: true + +# Package Mgmt +# Config Pkg Repos +rhel9cis_rule_1_2_1_1: true +rhel9cis_rule_1_2_1_2: true +rhel9cis_rule_1_2_1_3: true +rhel9cis_rule_1_2_1_4: true +# Package updates +rhel9cis_rule_1_2_2_1: true + +# Selinux +rhel9cis_rule_1_3_1_1: true +rhel9cis_rule_1_3_1_2: true +rhel9cis_rule_1_3_1_3: true +rhel9cis_rule_1_3_1_4: true +rhel9cis_rule_1_3_1_5: true +rhel9cis_rule_1_3_1_6: true +rhel9cis_rule_1_3_1_7: true +rhel9cis_rule_1_3_1_8: true + +# Bootloader rhel9cis_rule_1_4_1: true rhel9cis_rule_1_4_2: true + +# Additional Process Hardening rhel9cis_rule_1_5_1: true rhel9cis_rule_1_5_2: true rhel9cis_rule_1_5_3: true -rhel9cis_rule_1_6_1_1: true -rhel9cis_rule_1_6_1_2: true -rhel9cis_rule_1_6_1_3: true -rhel9cis_rule_1_6_1_4: true -rhel9cis_rule_1_6_1_5: true -rhel9cis_rule_1_6_1_6: true -rhel9cis_rule_1_6_1_7: true -rhel9cis_rule_1_6_1_8: true +rhel9cis_rule_1_5_4: true + +# Config system wide Crypto +rhel9cis_rule_1_6_1: true +rhel9cis_rule_1_6_2: true +rhel9cis_rule_1_6_3: true +rhel9cis_rule_1_6_4: true +rhel9cis_rule_1_6_5: true +rhel9cis_rule_1_6_6: true +rhel9cis_rule_1_6_7: true + +# Coomand line warning banners rhel9cis_rule_1_7_1: true rhel9cis_rule_1_7_2: true rhel9cis_rule_1_7_3: true rhel9cis_rule_1_7_4: true rhel9cis_rule_1_7_5: true rhel9cis_rule_1_7_6: true + +# Gnome Display Manager rhel9cis_rule_1_8_1: true rhel9cis_rule_1_8_2: true rhel9cis_rule_1_8_3: true @@ -190,8 +227,6 @@ rhel9cis_rule_1_8_7: true rhel9cis_rule_1_8_8: true rhel9cis_rule_1_8_9: true rhel9cis_rule_1_8_10: true -rhel9cis_rule_1_9: true -rhel9cis_rule_1_10: true # Section 2 rules are controling Services (Special Purpose Services, and service clients) rhel9cis_rule_2_1_1: true diff --git a/handlers/main.yml b/handlers/main.yml index dd97fec..69743d6 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -36,20 +36,34 @@ path: /tmp state: remounted +- 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 %}" + notify: Set Crypto Policy + +- name: Set Crypto Policy + when: rhel9cis_system_wide_crypto_policy.stdout != rhel9cis_full_crypto_policy + ansible.builtin.shell: | + update-crypto-policies --set "{{ rhel9cis_full_crypto_policy }}" + update-crypto-policies + notify: + - Change_requires_reboot + - Restart sshd + - name: Restart firewalld ansible.builtin.systemd: - name: firewalld - state: restarted + name: firewalld + state: restarted - name: Restart sshd ansible.builtin.systemd: - name: sshd - state: restarted + name: sshd + state: restarted - name: Restart postfix ansible.builtin.systemd: - name: postfix - state: restarted + name: postfix + state: restarted - name: Reload dconf ansible.builtin.shell: dconf update @@ -57,35 +71,33 @@ - name: Grub2cfg ansible.builtin.shell: "grub2-mkconfig -o /boot/grub2/grub.cfg" ignore_errors: true # noqa ignore-errors - tags: - - skip_ansible_lint - name: Restart rsyslog ansible.builtin.systemd: - name: rsyslog - state: restarted + name: rsyslog + state: restarted - name: Restart journald ansible.builtin.systemd: - name: systemd-journald - state: restarted + name: systemd-journald + state: restarted - name: Restart systemd_journal_upload ansible.builtin.systemd: - name: systemd-journal-upload - state: restarted + name: systemd-journal-upload + state: restarted - name: Systemd daemon reload ansible.builtin.systemd: - daemon-reload: true + daemon-reload: true - name: Apply_authselect - ansible.builtin.shell: authselect apply-changes when: not rhel9cis_rule_5_4_2 + ansible.builtin.shell: authselect apply-changes - name: Apply_authselect - ansible.builtin.shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} {{ rhel9cis_authselect['options'] }} --force --backup=rhel9cis_commit_{{ ansible_date_time.epoch}}" when: rhel9cis_rule_5_4_2 + ansible.builtin.shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} {{ rhel9cis_authselect['options'] }} --force --backup=rhel9cis_commit_{{ ansible_date_time.epoch}}" ## Auditd tasks note order for handlers to run - name: Auditd immutable check @@ -94,17 +106,15 @@ register: auditd_immutable_check - name: Audit immutable fact - ansible.builtin.debug: - msg: "Reboot required for auditd to apply new rules as immutable set" - notify: Change_requires_reboot when: - - auditd_immutable_check.stdout == '1' + - auditd_immutable_check.stdout == '1' + ansible.builtin.debug: + msg: "Reboot required for auditd to apply new rules as immutable set" + notify: Change_requires_reboot - name: Restart auditd ansible.builtin.shell: service auditd restart - tags: - - skip_ansible_lint - name: Change_requires_reboot ansible.builtin.set_fact: - change_requires_reboot: true + change_requires_reboot: true diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index 7ef94b4..b3964ce 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -2,33 +2,33 @@ - name: Pre Audit Setup | Set audit package name block: - - name: Pre Audit Setup | Set audit package name | 64bit - ansible.builtin.set_fact: - audit_pkg_arch_name: AMD64 - when: ansible_facts.machine == "x86_64" + - name: Pre Audit Setup | Set audit package name | 64bit + ansible.builtin.set_fact: + audit_pkg_arch_name: AMD64 + when: ansible_facts.machine == "x86_64" - - name: Pre Audit Setup | Set audit package name | ARM64 - ansible.builtin.set_fact: - audit_pkg_arch_name: ARM64 - when: ansible_facts.machine == "arm64" + - name: Pre Audit Setup | Set audit package name | ARM64 + ansible.builtin.set_fact: + audit_pkg_arch_name: ARM64 + when: ansible_facts.machine == "arm64" - name: Pre Audit Setup | Download audit binary ansible.builtin.get_url: - url: "{{ audit_bin_url }}{{ audit_pkg_arch_name }}" - dest: "{{ audit_bin }}" - owner: root - group: root - checksum: "{{ audit_bin_version[audit_pkg_arch_name + '_checksum'] }}" - mode: '0555' + url: "{{ audit_bin_url }}{{ audit_pkg_arch_name }}" + dest: "{{ audit_bin }}" + owner: root + group: root + checksum: "{{ audit_bin_version[audit_pkg_arch_name + '_checksum'] }}" + mode: '0555' when: - - get_audit_binary_method == 'download' + - get_audit_binary_method == 'download' - name: Pre Audit Setup | Copy audit binary ansible.builtin.copy: - src: "{{ audit_bin_copy_location }}" - dest: "{{ audit_bin }}" - mode: '0555' - owner: root - group: root + src: "{{ audit_bin_copy_location }}" + dest: "{{ audit_bin }}" + mode: '0555' + owner: root + group: root when: - - get_audit_binary_method == 'copy' + - get_audit_binary_method == 'copy' diff --git a/tasks/main.yml b/tasks/main.yml index 509ae27..b2c2695 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -3,224 +3,231 @@ - name: Check OS version and family ansible.builtin.assert: - that: (ansible_facts.distribution != 'CentOS' and ansible_facts.os_family == 'RedHat' or ansible_facts.os_family == "Rocky") and ansible_facts.distribution_major_version is version_compare('9', '==') - fail_msg: "This role can only be run against Supported OSs. {{ ansible_facts.distribution }} {{ ansible_facts.distribution_major_version }} is not supported." - success_msg: "This role is running against a supported OS {{ ansible_facts.distribution }} {{ ansible_facts.distribution_major_version }}" + that: (ansible_facts.distribution != 'CentOS' and ansible_facts.os_family == 'RedHat' or ansible_facts.os_family == "Rocky") and ansible_facts.distribution_major_version is version_compare('9', '==') + fail_msg: "This role can only be run against Supported OSs. {{ ansible_facts.distribution }} {{ ansible_facts.distribution_major_version }} is not supported." + success_msg: "This role is running against a supported OS {{ ansible_facts.distribution }} {{ ansible_facts.distribution_major_version }}" when: - - os_check + - os_check tags: - - always + - always - name: Check ansible version ansible.builtin.assert: - that: ansible_version.full is version_compare(min_ansible_version, '>=') - fail_msg: "You must use Ansible {{ min_ansible_version }} or greater" - success_msg: "This role is running a supported version of ansible {{ ansible_version.full }} >= {{ min_ansible_version }}" + that: ansible_version.full is version_compare(min_ansible_version, '>=') + fail_msg: "You must use Ansible {{ min_ansible_version }} or greater" + success_msg: "This role is running a supported version of ansible {{ ansible_version.full }} >= {{ min_ansible_version }}" tags: - - always + - always - name: "Check password set for {{ ansible_env.SUDO_USER }}" - block: - - name: "Check password set for {{ ansible_env.SUDO_USER }} | password state" - ansible.builtin.shell: "(grep {{ ansible_env.SUDO_USER }} /etc/shadow || echo 'not found:not found') | awk -F: '{print $2}'" - changed_when: false - failed_when: false - check_mode: false - register: rhel9cis_ansible_user_password_set - - - name: "Check for local account {{ ansible_env.SUDO_USER }} | Check for local account" - ansible.builtin.debug: - msg: "No local account found for {{ ansible_env.SUDO_USER }} user. Skipping local account checks." - when: - - rhel9cis_ansible_user_password_set.stdout == "not found" - - - name: "Check local account" - block: - - name: "Check password set for {{ ansible_env.SUDO_USER }} | Assert local password set" - ansible.builtin.assert: - that: - - rhel9cis_ansible_user_password_set.stdout | length != 0 - - rhel9cis_ansible_user_password_set.stdout != "!!" - fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} has no password set - It can break access" - success_msg: "You have a password set for the {{ ansible_env.SUDO_USER }} user" - - - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" - ansible.builtin.assert: - that: - - not rhel9cis_ansible_user_password_set.stdout.startswith("!") - 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" - when: - - rhel9cis_ansible_user_password_set.stdout != "not found" when: - - rhel9cis_rule_5_3_4 - - ansible_env.SUDO_USER is defined - - not system_is_ec2 + - rhel9cis_rule_5_3_4 + - ansible_env.SUDO_USER is defined + - not system_is_ec2 tags: - - user_passwd - - rule_5.3.4 + - user_passwd + - rule_5.3.4 vars: sudo_password_rule: rhel9cis_rule_5_3_4 # pragma: allowlist secret + block: + - name: "Check password set for {{ ansible_env.SUDO_USER }} | password state" + ansible.builtin.shell: "(grep {{ ansible_env.SUDO_USER }} /etc/shadow || echo 'not found:not found') | awk -F: '{print $2}'" + changed_when: false + failed_when: false + check_mode: false + register: rhel9cis_ansible_user_password_set + + - name: "Check for local account {{ ansible_env.SUDO_USER }} | Check for local account" + when: rhel9cis_ansible_user_password_set.stdout == "not found" + ansible.builtin.debug: + msg: "No local account found for {{ ansible_env.SUDO_USER }} user. Skipping local account checks." + + - name: "Check local account" + when: + - rhel9cis_ansible_user_password_set.stdout != "not found" + block: + - name: "Check password set for {{ ansible_env.SUDO_USER }} | Assert local password set" + ansible.builtin.assert: + that: + - rhel9cis_ansible_user_password_set.stdout | length != 0 + - rhel9cis_ansible_user_password_set.stdout != "!!" + fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} has no password set - It can break access" + success_msg: "You have a password set for the {{ ansible_env.SUDO_USER }} user" + + - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" + ansible.builtin.assert: + that: + - not rhel9cis_ansible_user_password_set.stdout.startswith("!") + 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: Ensure root password is set - block: - - name: Ensure root password is set - ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)" - changed_when: false - register: root_passwd_set - - - name: Ensure root password is set - ansible.builtin.assert: - that: root_passwd_set.rc == 0 - fail_msg: "You have rule 5.6.6 enabled this requires that you have a root password set" - success_msg: "You have a root password set" when: - - rhel9cis_rule_5_6_6 + - rhel9cis_rule_5_6_6 tags: - - level1-server - - level1-workstation - - patch - - accounts - - root - - rule_5.6.6 + - level1-server + - level1-workstation + - patch + - accounts + - root + - rule_5.6.6 + block: + - name: Ensure root password is set + ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)" + changed_when: false + register: root_passwd_set + + - name: Ensure root password is set + ansible.builtin.assert: + that: root_passwd_set.rc == 0 + fail_msg: "You have rule 5.6.6 enabled this requires that you have a root password set" + success_msg: "You have a root password set" - name: Setup rules if container - block: - - name: Discover and set container variable if required - ansible.builtin.set_fact: - system_is_container: true - - - name: Load variable for container - ansible.builtin.include_vars: - file: "{{ container_vars_file }}" - - - name: Output if discovered is a container - ansible.builtin.debug: - msg: system has been discovered as a container - when: - - system_is_container when: - - ansible_connection == 'docker' or - ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] + - ansible_connection == 'docker' or + ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] tags: - - container_discovery - - always + - container_discovery + - always + block: + - name: Discover and set container variable if required + ansible.builtin.set_fact: + system_is_container: true + + - name: Load variable for container + ansible.builtin.include_vars: + file: "{{ container_vars_file }}" + + - name: Output if discovered is a container + when: + - system_is_container + ansible.builtin.debug: + msg: system has been discovered as a container - name: Check crypto-policy input ansible.builtin.assert: - that: rhel9cis_crypto_policy in rhel9cis_allowed_crypto_policies - fail_msg: "Crypto policy is not a permitted version" - success_msg: "Crypto policy is a permitted version" + that: rhel9cis_crypto_policy in rhel9cis_allowed_crypto_policies + fail_msg: "Crypto policy is not a permitted version" + success_msg: "Crypto policy is a permitted version" - name: Check crypto-policy module input - ansible.builtin.assert: - that: rhel9cis_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" when: - - rhel9cis_rule_1_10 - - rhel9cis_crypto_policy_module | length > 0 + - rhel9cis_rule_1_6_1 + - rhel9cis_crypto_policy_module | length > 0 tags: - - rule_1.10 + - rule_1.6.1 + ansible.builtin.assert: + that: rhel9cis_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" - name: Check rhel9cis_bootloader_password_hash variable has been changed - ansible.builtin.assert: - that: rhel9cis_bootloader_password_hash.find('grub.pbkdf2.sha512') != -1 and rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret - msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password_hash variable has not been set correctly" when: - - rhel9cis_set_boot_pass - - rhel9cis_rule_1_4_1 + - rhel9cis_set_boot_pass + - rhel9cis_rule_1_4_1 tags: - - always + - always + ansible.builtin.assert: + that: rhel9cis_bootloader_password_hash.find('grub.pbkdf2.sha512') != -1 and rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret + msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password_hash variable has not been set correctly" - name: Gather the package facts - ansible.builtin.package_facts: - manager: auto tags: - - always + - always + ansible.builtin.package_facts: + manager: auto - name: Include OS specific variables - ansible.builtin.include_vars: "{{ ansible_facts.distribution }}.yml" tags: - - always + - always + ansible.builtin.include_vars: + file: "{{ ansible_facts.distribution }}.yml" - name: Include preliminary steps - ansible.builtin.import_tasks: - file: prelim.yml tags: - - prelim_tasks - - always + - prelim_tasks + - always + ansible.builtin.import_tasks: + file: prelim.yml - name: Run Section 1 tasks - ansible.builtin.import_tasks: - file: section_1/main.yml when: rhel9cis_section1 tags: - - rhel9cis_section1 + - rhel9cis_section1 + ansible.builtin.import_tasks: + file: section_1/main.yml - name: Run Section 2 tasks - ansible.builtin.import_tasks: - file: section_2/main.yml when: rhel9cis_section2 tags: - - rhel9cis_section2 + - rhel9cis_section2 + ansible.builtin.import_tasks: + file: section_2/main.yml - name: Run Section 3 tasks - ansible.builtin.import_tasks: - file: section_3/main.yml when: rhel9cis_section3 tags: - - rhel9cis_section3 + - rhel9cis_section3 + ansible.builtin.import_tasks: + file: section_3/main.yml - name: Run Section 4 tasks - ansible.builtin.import_tasks: - file: section_4/main.yml when: rhel9cis_section4 tags: - - rhel9cis_section4 + - rhel9cis_section4 + ansible.builtin.import_tasks: + file: section_4/main.yml - name: Run Section 5 tasks - ansible.builtin.import_tasks: - file: section_5/main.yml when: rhel9cis_section5 tags: - - rhel9cis_section5 + - rhel9cis_section5 + ansible.builtin.import_tasks: + file: section_5/main.yml - name: Run Section 6 tasks - ansible.builtin.import_tasks: - file: section_6/main.yml when: rhel9cis_section6 tags: - - rhel9cis_section6 + - rhel9cis_section6 + ansible.builtin.import_tasks: + file: section_6/main.yml + +# - name: Run Section 7 tasks +# when: rhel9cis_section7 +# tags: +# - rhel9cis_section7 +# ansible.builtin.import_tasks: +# file: section_7/main.yml - name: Run auditd logic - ansible.builtin.import_tasks: - file: auditd.yml when: update_audit_template tags: - - always + - always + ansible.builtin.import_tasks: + file: auditd.yml - name: Run post remediation tasks - ansible.builtin.import_tasks: - file: post.yml tags: - - post_tasks - - always + - post_tasks + - always + ansible.builtin.import_tasks: + file: post.yml - name: Run post_remediation audit - ansible.builtin.import_tasks: - file: post_remediation_audit.yml when: - - run_audit + - run_audit + ansible.builtin.import_tasks: + file: post_remediation_audit.yml - name: Show Audit Summary - ansible.builtin.debug: - msg: "{{ audit_results.split('\n') }}" when: run_audit + ansible.builtin.debug: + msg: "{{ audit_results.split('\n') }}" - name: If Warnings found Output count and control IDs affected - ansible.builtin.debug: - msg: "You have {{ warn_count }} Warning(s) that require investigating that are related to the following benchmark ID(s) {{ warn_control_list }}" when: warn_count != 0 tags: - always + ansible.builtin.debug: + msg: "You have {{ warn_count }} Warning(s) that require investigating that are related to the following benchmark ID(s) {{ warn_control_list }}" diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 8ff13fd..e16f8b9 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -1,32 +1,32 @@ --- - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd" - block: - - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd" - ansible.builtin.shell: cat /etc/passwd - changed_when: false - check_mode: false - register: rhel9cis_passwd_file_audit - - - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries" - ansible.builtin.set_fact: - rhel9cis_passwd: "{{ rhel9cis_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" - loop: "{{ rhel9cis_passwd_file_audit.stdout_lines }}" - vars: - ld_passwd_regex: >- - ^(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*) - ld_passwd_yaml: | - id: >-4 - \g - password: >-4 - \g - uid: \g - gid: \g - gecos: >-4 - \g - dir: >-4 - \g - shell: >-4 - \g tags: - - always + - always + block: + - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd" + ansible.builtin.shell: cat /etc/passwd + changed_when: false + check_mode: false + register: rhel9cis_passwd_file_audit + + - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries" + ansible.builtin.set_fact: + rhel9cis_passwd: "{{ rhel9cis_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" + loop: "{{ rhel9cis_passwd_file_audit.stdout_lines }}" + vars: + ld_passwd_regex: >- + ^(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*) + ld_passwd_yaml: | + id: >-4 + \g + password: >-4 + \g + uid: \g + gid: \g + gecos: >-4 + \g + dir: >-4 + \g + shell: >-4 + \g diff --git a/tasks/post.yml b/tasks/post.yml index 3f1f706..59766f5 100644 --- a/tasks/post.yml +++ b/tasks/post.yml @@ -2,12 +2,16 @@ # Post tasks - name: POST | Gather the package facts after remediation - ansible.builtin.package_facts: - manager: auto tags: - - always + - always + ansible.builtin.package_facts: + manager: auto - name: POST | Update sysctl + when: + - rhel9cis_sysctl_update + - not system_is_container + - "'procps-ng' in ansible_facts.packages" ansible.builtin.template: src: "etc/sysctl.d/{{ item }}.j2" dest: "/etc/sysctl.d/{{ item }}" @@ -21,47 +25,33 @@ - 60-disable_ipv6.conf - 60-netipv4_sysctl.conf - 60-netipv6_sysctl.conf - when: - - rhel9cis_sysctl_update - - not system_is_container - - "'procps-ng' in ansible_facts.packages" - name: Flush handlers ansible.builtin.meta: flush_handlers - name: POST | reboot system if changes require it and not skipped - block: - - name: POST | Reboot system if changes require it and not skipped - ansible.builtin.reboot: - when: - - change_requires_reboot - - not skip_reboot - - - name: POST | Warning a reboot required but skip option set - ansible.builtin.debug: - msg: "Warning!! changes have been made that require a reboot to be implemented but skip reboot was set - Can affect compliance check results" - changed_when: true - when: - - change_requires_reboot - - skip_reboot - - - name: "POST | Warning a reboot required but skip option set | warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml - when: - - change_requires_reboot - - skip_reboot - vars: - warn_control_id: Reboot_required tags: - - grub - - level1-server - - level1-workstation - - level2-server - - level2-workstation - - rhel9cis_section1 - - rhel9cis_section2 - - rhel9cis_section3 - - rhel9cis_section4 - - rhel9cis_section5 - - rhel9cis_section6 + - always + block: + - name: POST | Reboot system if changes require it and not skipped + ansible.builtin.reboot: + when: + - change_requires_reboot + - not skip_reboot + + - name: POST | Warning a reboot required but skip option set + ansible.builtin.debug: + msg: "Warning!! changes have been made that require a reboot to be implemented but skip reboot was set - Can affect compliance check results" + changed_when: true + when: + - change_requires_reboot + - skip_reboot + + - name: "POST | Warning a reboot required but skip option set | warning count" + ansible.builtin.import_tasks: + file: warning_facts.yml + when: + - change_requires_reboot + - skip_reboot + vars: + warn_control_id: Reboot_required diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index d58e921..a6f9461 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -4,41 +4,41 @@ ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" changed_when: true environment: - AUDIT_BIN: "{{ audit_bin }}" - AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" - AUDIT_FILE: goss.yml + AUDIT_BIN: "{{ audit_bin }}" + AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" + AUDIT_FILE: goss.yml -- name: Post Audit | ensure audit files readable by users +- name: Post Audit | Ensure audit files readable by users ansible.builtin.file: - path: "{{ item }}" - mode: '0644' - state: file + path: "{{ item }}" + mode: '0644' + state: file loop: - - "{{ post_audit_outfile }}" - - "{{ pre_audit_outfile }}" + - "{{ post_audit_outfile }}" + - "{{ pre_audit_outfile }}" - name: Post Audit | Capture audit data if json format when: - - audit_format == "json" + - audit_format == "json" block: - - name: Post Audit | Capture audit data if json format - ansible.builtin.shell: grep -E '"summary-line.*Count:.*Failed' "{{ post_audit_outfile }}" | cut -d'"' -f4 - register: post_audit_summary - changed_when: false + - name: Post Audit | Capture audit data if json format + ansible.builtin.shell: grep -E '"summary-line.*Count:.*Failed' "{{ post_audit_outfile }}" | cut -d'"' -f4 + register: post_audit_summary + changed_when: false - - name: Post Audit | Set Fact for audit summary - ansible.builtin.set_fact: - post_audit_results: "{{ post_audit_summary.stdout }}" + - name: Post Audit | Set Fact for audit summary + ansible.builtin.set_fact: + post_audit_results: "{{ post_audit_summary.stdout }}" - name: Post Audit | Capture audit data if documentation format when: - - audit_format == "documentation" + - audit_format == "documentation" block: - - name: Post Audit | Capture audit data if documentation format - ansible.builtin.shell: "tail -2 /opt/audit_ubuntu2204-CIS-UBUNTU22_1720624848.documentation" - register: post_audit_summary - changed_when: false + - name: Post Audit | Capture audit data if documentation format + ansible.builtin.shell: "tail -2 /opt/audit_ubuntu2204-CIS-UBUNTU22_1720624848.documentation" + register: post_audit_summary + changed_when: false - - name: Post Audit | Set Fact for audit summary - ansible.builtin.set_fact: - post_audit_results: "{{ post_audit_summary.stdout }}" + - name: Post Audit | Set Fact for audit summary + ansible.builtin.set_fact: + post_audit_results: "{{ post_audit_summary.stdout }}" diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 5a99844..266603e 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -2,118 +2,118 @@ - name: Pre Audit Setup | Setup the LE audit when: - - setup_audit + - setup_audit tags: - - setup_audit + - setup_audit ansible.builtin.include_tasks: - file: LE_audit_setup.yml + file: LE_audit_setup.yml - name: Pre Audit Setup | Ensure {{ audit_conf_dir }} exists ansible.builtin.file: - path: "{{ audit_conf_dir }}" - state: directory - mode: '0755' + path: "{{ audit_conf_dir }}" + state: directory + mode: '0755' - name: Pre Audit Setup | If using git for content set up when: - - audit_content == 'git' + - audit_content == 'git' block: - - name: Pre Audit Setup | Install git - ansible.builtin.package: - name: git - state: present + - name: Pre Audit Setup | Install git + ansible.builtin.package: + name: git + state: present - - name: Pre Audit Setup | Retrieve audit content files from git - ansible.builtin.git: - repo: "{{ audit_file_git }}" - dest: "{{ audit_conf_dir }}" - version: "{{ audit_git_version }}" + - name: Pre Audit Setup | Retrieve audit content files from git + ansible.builtin.git: + repo: "{{ audit_file_git }}" + dest: "{{ audit_conf_dir }}" + version: "{{ audit_git_version }}" - name: Pre Audit Setup | Copy to audit content files to server when: - - audit_content == 'copy' + - audit_content == 'copy' ansible.builtin.copy: - src: "{{ audit_conf_source }}" - dest: "{{ audit_conf_dest }}" - mode: preserve + src: "{{ audit_conf_source }}" + dest: "{{ audit_conf_dest }}" + mode: preserve - name: Pre Audit Setup | Unarchive audit content files on server when: - - audit_content == 'archive' + - audit_content == 'archive' ansible.builtin.unarchive: - src: "{{ audit_conf_source }}" - dest: "{{ audit_conf_dest }}" + src: "{{ audit_conf_source }}" + dest: "{{ audit_conf_dest }}" - name: Pre Audit Setup | Get audit content from url when: - - audit_content == 'get_url' + - audit_content == 'get_url' ansible.builtin.unarchive: - src: "{{ audit_conf_source }}" - dest: "{{ audit_conf_dest }}/{{ benchmark }}-Audit" - remote_src: "{{ ( audit_conf_source is contains ('http'))| ternary(true, false ) }}" - extra_opts: "{{ (audit_conf_source is contains ('github')) | ternary('--strip-components=1', [] ) }}" + src: "{{ audit_conf_source }}" + dest: "{{ audit_conf_dest }}/{{ benchmark }}-Audit" + remote_src: "{{ ( audit_conf_source is contains ('http'))| ternary(true, false ) }}" + extra_opts: "{{ (audit_conf_source is contains ('github')) | ternary('--strip-components=1', [] ) }}" - name: Pre Audit Setup | Check Goss is available when: - - run_audit + - run_audit block: - - name: Pre Audit Setup | Check for goss file - ansible.builtin.stat: - path: "{{ audit_bin }}" - register: goss_available + - name: Pre Audit Setup | Check for goss file + ansible.builtin.stat: + path: "{{ audit_bin }}" + register: goss_available - - name: Pre Audit Setup | If audit ensure goss is available - ansible.builtin.assert: - that: goss_available.stat.exists - msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}" + - name: Pre Audit Setup | If audit ensure goss is available + ansible.builtin.assert: + that: goss_available.stat.exists + msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}" - name: Pre Audit Setup | Copy ansible default vars values to test audit tags: - - goss_template - - run_audit + - goss_template + - run_audit when: - - run_audit + - run_audit ansible.builtin.template: - src: ansible_vars_goss.yml.j2 - dest: "{{ audit_vars_path }}" - mode: '0600' + src: ansible_vars_goss.yml.j2 + dest: "{{ audit_vars_path }}" + mode: '0600' - name: Pre Audit | Run pre_remediation {{ benchmark }} audit ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" changed_when: true environment: - AUDIT_BIN: "{{ audit_bin }}" - AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" - AUDIT_FILE: goss.yml + AUDIT_BIN: "{{ audit_bin }}" + AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" + AUDIT_FILE: goss.yml - name: Pre Audit | Capture audit data if json format when: - - audit_format == "json" + - audit_format == "json" block: - - name: Pre Audit | Capture audit data if json format - ansible.builtin.shell: grep -E '\"summary-line.*Count:.*Failed' "{{ pre_audit_outfile }}" | cut -d'"' -f4 - register: pre_audit_summary - changed_when: false + - name: Pre Audit | Capture audit data if json format + ansible.builtin.shell: grep -E '\"summary-line.*Count:.*Failed' "{{ pre_audit_outfile }}" | cut -d'"' -f4 + register: pre_audit_summary + changed_when: false - - name: Pre Audit | Set Fact for audit summary - ansible.builtin.set_fact: - pre_audit_results: "{{ pre_audit_summary.stdout }}" + - name: Pre Audit | Set Fact for audit summary + ansible.builtin.set_fact: + pre_audit_results: "{{ pre_audit_summary.stdout }}" - name: Pre Audit | Capture audit data if documentation format when: - - audit_format == "documentation" + - audit_format == "documentation" block: - - name: Pre Audit | Capture audit data if documentation format - ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' - register: pre_audit_summary - changed_when: false + - name: Pre Audit | Capture audit data if documentation format + ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' + register: pre_audit_summary + changed_when: false - - name: Pre Audit | Set Fact for audit summary - ansible.builtin.set_fact: - pre_audit_results: "{{ pre_audit_summary.stdout }}" + - name: Pre Audit | Set Fact for audit summary + ansible.builtin.set_fact: + pre_audit_results: "{{ pre_audit_summary.stdout }}" - name: Audit_Only | Run Audit Only when: - - audit_only + - audit_only ansible.builtin.import_tasks: - file: audit_only.yml + file: audit_only.yml diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 0db27d3..c6ecbda 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -5,50 +5,51 @@ - name: PRELIM | Include audit specific variables when: - - run_audit or audit_only - - setup_audit + - run_audit or audit_only + - setup_audit tags: - - setup_audit - - run_audit - ansible.builtin.include_vars: audit.yml + - setup_audit + - run_audit + ansible.builtin.include_vars: + file: audit.yml - name: PRELIM | Include pre-remediation audit tasks when: - - run_audit or audit_only - - setup_audit + - run_audit or audit_only + - setup_audit tags: - run_audit ansible.builtin.import_tasks: pre_remediation_audit.yml - name: "PRELIM | AUDIT | Interactive Users" tags: - - always + - 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 $1 }' + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false" && $7 != "/dev/null") { print $1 }' changed_when: false - register: discovered_interactive_usernames + register: prelim_interactive_usernames - name: "PRELIM | AUDIT | Interactive User accounts home directories" tags: - - always + - always ansible.builtin.shell: > - grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $6 }' + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $6 }' changed_when: false - register: discovered_interactive_users_home + register: prelim_interactive_users_home - name: "PRELIM | AUDIT | Interactive UIDs" tags: - - always + - always ansible.builtin.shell: > - grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $3 }' + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $3 }' changed_when: false - register: discovered_interactive_uids + register: prelim_interactive_uids - name: "PRELIM | capture /etc/password variables" ansible.builtin.include_tasks: - file: parse_etc_password.yml + file: parse_etc_password.yml tags: - - always + - always - name: "PRELIM | List users accounts" ansible.builtin.shell: "awk -F: '{print $1}' /etc/passwd" @@ -56,9 +57,9 @@ check_mode: false register: users tags: - - level1-server - - level1-workstation - - users + - level1-server + - level1-workstation + - users - name: "PRELIM | Gather accounts with empty password fields" ansible.builtin.shell: "cat /etc/shadow | awk -F: '($2 == \"\" ) {j++;print $1; } END {exit j}'" @@ -66,63 +67,16 @@ check_mode: false register: empty_password_accounts tags: - - level1-server - - level1-workstation - - passwords + - level1-server + - level1-workstation + - passwords -- name: "PRELIM | Gather UID 0 accounts other than root" - ansible.builtin.shell: "cat /etc/passwd | awk -F: '($3 == 0 && $1 != \"root\") {i++;print $1 } END {exit i}'" - changed_when: false - check_mode: false - register: rhel9cis_uid_zero_accounts_except_root - tags: - - rule_6.2.9 - - level1-server - - level1-workstation - - users - -- name: "PRELIM | Setup crypto-policy" - block: - - name: "PRELIM | Install crypto-policies | pkgs present" - ansible.builtin.package: - name: - - crypto-policies - - crypto-policies-scripts - state: present - - - name: "PRELIM | Gather system-wide crypto-policy" - ansible.builtin.shell: 'update-crypto-policies --show' - changed_when: false - check_mode: false - register: rhel9cis_system_wide_crypto_policy - - - name: "PRELIM | Gather system-wide crypto-policy | set fact system policy" - ansible.builtin.set_fact: - current_crypto_policy: "{{ rhel9cis_system_wide_crypto_policy.stdout.split(':')[0] }}" - - - name: "PRELIM | Gather system-wide crypto-policy module | set fact system policy submodule" - ansible.builtin.set_fact: - current_crypto_module: "{{ rhel9cis_system_wide_crypto_policy.stdout.split(':')[1] }}" - when: "':' in rhel9cis_system_wide_crypto_policy.stdout" +- name: "PRELIM | Ensure python3-libselinux is installed" + ansible.builtin.package: + name: python3-libselinux + state: present when: - - rhel9cis_rule_1_10 - tags: - - level1-server - - level1-workstation - - rule_1.10 - - crypto - -- name: "PRELIM | if systemd coredump" - ansible.builtin.stat: - path: /etc/systemd/coredump.conf - register: systemd_coredump - when: - - rhel9cis_rule_1_5_1 - tags: - - level1-server - - level1-workstation - - rule_1.5.1 - - systemd + - '"python3-libselinux" not in ansible_facts.packages' - name: "PRELIM | Section 1.1 | Create list of mount points" ansible.builtin.set_fact: @@ -131,79 +85,115 @@ - level1-server - level1-workstation -- name: "PRELIM | Ensure python3-libselinux is installed" - ansible.builtin.package: - name: python3-libselinux - state: present - when: - - '"python3-libselinux" not in ansible_facts.packages' - -- name: "PRELIM | Set facts based on boot type" - block: - - name: "PRELIM | Check whether machine is UEFI-based" - ansible.builtin.stat: - path: /sys/firmware/efi - register: rhel_09_efi_boot - - - name: "PRELIM | set legacy boot and grub path | Bios" - ansible.builtin.set_fact: - rhel9cis_legacy_boot: true - grub2_path: /etc/grub2.cfg - when: not rhel_09_efi_boot.stat.exists - - - name: "PRELIM | set grub fact | UEFI" - ansible.builtin.set_fact: - grub2_path: /etc/grub2-efi.cfg - when: rhel_09_efi_boot.stat.exists - - name: "PRELIM | Update to latest gpg keys" ansible.builtin.package: name: "{{ gpg_key_package }}" state: latest when: - - rhel9cis_rule_1_2_4 + - rhel9cis_rule_1_2_1_1 - ansible_facts.distribution != 'RedHat' - ansible_facts.distribution != 'OracleLinux' -- name: "PRELIM | Check gpg keys are imported will cause 1.2.1 to fail if not | RedHat Only" +- name: "PRELIM | Check gpg keys are imported will cause 1.2.1.1 to fail if not | RedHat Only" block: - - name: "PRELIM | Check gpg keys are imported will cause 1.2.1 to fail if not" - ansible.builtin.shell: rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' - changed_when: false - failed_when: false - register: check_gpg_imported + - name: "PRELIM | Check gpg keys are imported will cause 1.2.1.1 to fail if not" + ansible.builtin.shell: rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' + changed_when: false + failed_when: false + register: check_gpg_imported - - name: "PRELIM | Check key package matches RedHat" - ansible.builtin.shell: rpm -qi redhat-release | grep Signature - changed_when: false - failed_when: false - register: os_gpg_package_valid - when: "'not installed' in check_gpg_imported.stdout" + - name: "PRELIM | Check key package matches RedHat" + ansible.builtin.shell: rpm -qi redhat-release | grep Signature + changed_when: false + failed_when: false + register: os_gpg_package_valid + when: "'not installed' in check_gpg_imported.stdout" - - name: "PRELIM | Force keys to be imported" - ansible.builtin.shell: rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release - when: - - "'not installed' in check_gpg_imported.stdout" - - "'Key ID 199e2f91fd431d51' in os_gpg_package_valid.stdout" + - name: "PRELIM | Force keys to be imported" + ansible.builtin.shell: rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release + when: + - "'not installed' in check_gpg_imported.stdout" + - "'Key ID 199e2f91fd431d51' in os_gpg_package_valid.stdout" when: - - rhel9cis_rule_1_2_1 - - rhel9cis_force_gpg_key_import - - ansible_facts.distribution == 'RedHat' + - rhel9cis_rule_1_2_1_1 + - rhel9cis_force_gpg_key_import + - ansible_facts.distribution == 'RedHat' + +- name: "PRELIM | if systemd coredump" + ansible.builtin.stat: + path: /etc/systemd/coredump.conf + register: systemd_coredump + when: + - rhel9cis_rule_1_5_4 + tags: + - level1-server + - level1-workstation + - rule_1.5.4 + - systemd + +- name: "PRELIM | Setup crypto-policy" + block: + - name: "PRELIM | Install crypto-policies | pkgs present" + ansible.builtin.package: + name: + - crypto-policies + - crypto-policies-scripts + state: present + + - name: "PRELIM | Gather system-wide crypto-policy" + ansible.builtin.shell: 'update-crypto-policies --show' + changed_when: false + check_mode: false + register: rhel9cis_system_wide_crypto_policy + + - name: "PRELIM | Gather system-wide crypto-policy | set fact system policy" + ansible.builtin.set_fact: + current_crypto_policy: "{{ rhel9cis_system_wide_crypto_policy.stdout.split(':')[0] }}" + + - name: "PRELIM | Gather system-wide crypto-policy module | set fact system policy submodule" + ansible.builtin.set_fact: + current_crypto_module: "{{ rhel9cis_system_wide_crypto_policy.stdout.split(':')[1] }}" + when: "':' in rhel9cis_system_wide_crypto_policy.stdout" + when: + - rhel9cis_rule_1_6_1 + tags: + - level1-server + - level1-workstation + - rule_1.6.1 + - crypto + +- name: "PRELIM | Set facts based on boot type" + block: + - name: "PRELIM | Check whether machine is UEFI-based" + ansible.builtin.stat: + path: /sys/firmware/efi + register: rhel_09_efi_boot + + - name: "PRELIM | set legacy boot and grub path | Bios" + ansible.builtin.set_fact: + rhel9cis_legacy_boot: true + grub2_path: /etc/grub2.cfg + when: not rhel_09_efi_boot.stat.exists + + - name: "PRELIM | set grub fact | UEFI" + ansible.builtin.set_fact: + grub2_path: /etc/grub2-efi.cfg + when: rhel_09_efi_boot.stat.exists - name: "PRELIM | Section 4.1 | Configure System Accounting (auditd)" ansible.builtin.package: - name: audit - state: present + name: audit + state: present become: true when: - - '"auditd" not in ansible_facts.packages' - - rhel9cis_rule_4_1_1_1 + - '"auditd" not in ansible_facts.packages' + - rhel9cis_rule_4_1_1_1 tags: - - level2-server - - level2-workstation - - patch - - rule_4.1.1.1 - - auditd + - level2-server + - level2-workstation + - patch + - rule_4.1.1.1 + - auditd - name: "PRELIM | 4.1.4.5 | Audit conf and rules files | list files" ansible.builtin.find: @@ -268,6 +258,17 @@ - rule_5.3.4 - rule_5.3.5 +- name: "PRELIM | Gather UID 0 accounts other than root" + ansible.builtin.shell: "cat /etc/passwd | awk -F: '($3 == 0 && $1 != \"root\") {i++;print $1 } END {exit i}'" + changed_when: false + check_mode: false + register: rhel9cis_uid_zero_accounts_except_root + tags: + - rule_6.2.9 + - level1-server + - level1-workstation + - users + - name: "PRELIM | Discover Interactive UID MIN and MIN from logins.def" block: - name: "PRELIM | Capture UID_MIN information from logins.def" diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index 263fc50..8ea6909 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -1,66 +1,303 @@ --- -- name: "1.1.1.1 | PATCH | Ensure mounting of squashfs filesystems is disabled" - block: - - name: "1.1.1.1 | PATCH | Ensure mounting of squashfs filesystems is disabled | Edit modprobe config" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/CIS.conf - regexp: "^(#)?install squashfs(\\s|$)" - line: "install squashfs /bin/true" - create: true - mode: '0600' - - - name: "1.1.1.1 | PATCH | Ensure mounting of squashfs filesystems is disabled | blacklist" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/blacklist.conf - regexp: "^(#)?blacklist squashfs(\\s|$)" - line: "blacklist squashfs" - create: true - mode: '0600' - - - name: "1.1.1.1 | PATCH | Ensure mounting of squashfs filesystems is disabled | Disable squashfs" - community.general.modprobe: - name: squashfs - state: absent - when: not system_is_container - +- name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available" when: - - rhel9cis_rule_1_1_1_1 + - rhel9cis_rule_1_1_1_1 tags: - - level2-server - - level2-workstation - - patch - - rule_1.1.1.1 - - squashfs - -- name: "1.1.1.2 | PATCH | Ensure mounting of udf filesystems is disabled" + - level1-server + - level1-workstation + - patch + - rule_1.1.1.1 + - cramfs block: - - name: "1.1.1.2 | PATCH | Ensure mounting of udf filesystems is disable | Edit modprobe config" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/CIS.conf - regexp: "^(#)?install udf(\\s|$)" - line: "install udf /bin/true" - create: true - mode: '0600' + - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install cramfs(\\s|$)" + line: "install cramfs /bin/true" + create: true + mode: '0600' - - name: "1.1.1.2 | PATCH | Ensure mounting of udf filesystems is disabled | blacklist" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/blacklist.conf - regexp: "^(#)?blacklist udf(\\s|$)" - line: "blacklist udf" - create: true - mode: '0600' + - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist cramfs(\\s|$)" + line: "blacklist cramfs" + create: true + mode: '0600' - - name: "1.1.1.2 | PATCH | Ensure mounting of udf filesystems is disable | Disable udf" - community.general.modprobe: - name: udf - state: absent - when: not system_is_container + - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | Disable cramfs" + when: + - not system_is_container + community.general.modprobe: + name: cramfs + state: absent + +- name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available" when: - - rhel9cis_rule_1_1_1_2 + - rhel9cis_rule_1_1_1_2 tags: - - level2-server - - level2-workstation - - patch - - rule_1.1.1.2 - - udf + - level1-server + - level1-workstation + - patch + - rule_1.1.1.2 + - freevxfs + block: + - name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install freevxfs(\\s|$)" + line: "install freevxfs /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist freevxfs(\\s|$)" + line: "blacklist freevxfs" + create: true + mode: '0600' + + - name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | Disable freevxfs" + when: + - not system_is_container + community.general.modprobe: + name: freevxfs + state: absent + +- name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available" + when: + - rhel9cis_rule_1_1_1_3 + tags: + - level1-server + - level1-workstation + - patch + - rule_1.1.1.3 + - hfs + block: + - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install hfs(\\s|$)" + line: "install hfs /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist hfs(\\s|$)" + line: "blacklist hfs" + create: true + mode: '0600' + + - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | Disable hfs" + when: + - not system_is_container + community.general.modprobe: + name: hfs + state: absent + +- name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available" + when: + - rhel9cis_rule_1_1_1_4 + tags: + - level1-server + - level1-workstation + - patch + - rule_1.1.1.4 + - hfsplus + block: + - name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install hfsplus(\\s|$)" + line: "install hfsplus /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist hfsplus(\\s|$)" + line: "blacklist hfsplus" + create: true + mode: '0600' + + - name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | Disable hfsplus" + when: + - not system_is_container + community.general.modprobe: + name: hfsplus + state: absent + +- name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available" + when: + - rhel9cis_rule_1_1_1_5 + tags: + - level1-server + - level1-workstation + - patch + - rule_1.1.1.5 + - jffs2 + block: + - name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install jffs2(\\s|$)" + line: "install jffs2 /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist jffs2(\\s|$)" + line: "blacklist jffs2" + create: true + mode: '0600' + + - name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | Disable jffs2" + when: + - not system_is_container + community.general.modprobe: + name: jffs2 + state: absent + +- name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available" + when: + - rhel9cis_rule_1_1_1_6 + tags: + - level2-server + - level2-workstation + - patch + - rule_1.1.1.6 + - squashfs + block: + - name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install squashfs(\\s|$)" + line: "install squashfs /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist squashfs(\\s|$)" + line: "blacklist squashfs" + create: true + mode: '0600' + + - name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | Disable squashfs" + when: + - not system_is_container + community.general.modprobe: + name: squashfs + state: absent + +- name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available" + when: + - rhel9cis_rule_1_1_1_7 + tags: + - level2-server + - level2-workstation + - patch + - rule_1.1.1.7 + - udf + block: + - name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install udf(\\s|$)" + line: "install udf /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist udf(\\s|$)" + line: "blacklist udf" + create: true + mode: '0600' + + - name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | Disable udf" + when: + - not system_is_container + community.general.modprobe: + name: udf + state: absent + +- name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available" + when: + - rhel9cis_rule_1_1_1_8 + tags: + - level1-server + - level2-workstation + - patch + - rule_1.1.1.8 + - usb + block: + - name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install usb-storage(\\s|$)" + line: "install usb-storage /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist usb-storage(\\s|$)" + line: "blacklist usb-storage" + create: true + mode: '0600' + + - name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | Disable usb" + when: + - not system_is_container + community.general.modprobe: + name: usb-storage + state: absent + +- name: "1.1.1.9 | PATCH | Ensure unused filesystems kernel modules are not available" + when: + - rhel9cis_rule_1_1_1_9 + tags: + - level1-server + - level1-workstation + - patch + - rule_1.1.1.9 + - usb + vars: + warn_control_id: '1.1.1.9' + block: + - name: "1.1.1.9 | PATCH | Ensure unused filesystems kernel modules are not available | Add discovery script" + ansible.builtin.template: + src: fs_with_cves.sh + dest: /var/fs_with_cves.sh + owner: root + group: root + mode: '0744' + + - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Run discovery script" + ansible.builtin.shell: /var/fs_with_cves.sh + changed_when: false + failed_when: discovered_fs_modules_loaded.rc not in [ 0, 99 ] + register: discovered_fs_modules_loaded + + - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Output Warning" + when: discovered_fs_modules_loaded.stdout | length > 0 + ansible.builtin.debug: + msg: | + "Warning!! Discovered loaded Filesystem modules that need attention. This is a manual task + {{ discovered_fs_modules_loaded.stdout_lines}}" + + - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Capture Warning" + when: discovered_fs_modules_loaded.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml diff --git a/tasks/section_1/cis_1.1.2.1.x.yml b/tasks/section_1/cis_1.1.2.1.x.yml new file mode 100644 index 0000000..cd27f5e --- /dev/null +++ b/tasks/section_1/cis_1.1.2.1.x.yml @@ -0,0 +1,83 @@ +--- + +- name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition" + when: + - required_mount not in mount_names + - rhel9cis_rule_1_1_2_1_1 + tags: + - level1-server + - level1-workstation + - audit + - mounts + - rule_1.1.2.1.1 + vars: + warn_control_id: '1.1.2.1.1' + required_mount: '/tmp' + block: + - name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + + - name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +# via fstab +- name: | + "1.1.2.1.2 | PATCH | Ensure nodev option set on /tmp partition" + "1.1.2.1.3 | PATCH | Ensure nosuid option set on /tmp partition" + "1.1.2.1.4 | PATCH | Ensure noexec option set on /tmp partition" + ansible.posix.mount: + name: /tmp + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel9cis_rule_1_1_2_1_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_1_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_1_4 %}noexec{% endif %} + notify: Remount tmp + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + when: + - item.mount == "/tmp" + - not rhel9cis_tmp_svc + - rhel9cis_rule_1_1_2_1_2 or + rhel9cis_rule_1_1_2_1_3 or + rhel9cis_rule_1_1_2_1_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1.1.2.1.2 + - rule_1.1.2.1.3 + - rule_1.1.2.1.4 + +# via systemd +- name: | + "1.1.2.1.1 | PATCH | Ensure /tmp is configured" + "1.1.2.1.2 | PATCH | Ensure nodev option set on /tmp partition" + "1.1.2.1.3 | PATCH | Ensure noexec option set on /tmp partition" + "1.1.2.1.4 | PATCH | Ensure nosuid option set on /tmp partition" + when: + - rhel9cis_tmp_svc + - rhel9cis_rule_1_1_2_1_1 or + rhel9cis_rule_1_1_2_1_2 or + rhel9cis_rule_1_1_2_1_3 or + rhel9cis_rule_1_1_2_1_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1.1.2.1.1 + - rule_1.1.2.1.2 + - rule_1.1.2.1.3 + - rule_1.1.2.1.4 + ansible.builtin.template: + src: etc/systemd/system/tmp.mount.j2 + dest: /etc/systemd/system/tmp.mount + owner: root + group: root + mode: '0644' + notify: Systemd restart tmp.mount + diff --git a/tasks/section_1/cis_1.1.2.2.x.yml b/tasks/section_1/cis_1.1.2.2.x.yml new file mode 100644 index 0000000..0831626 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.2.x.yml @@ -0,0 +1,54 @@ +--- + +# Skips if mount is absent +- name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition" + when: + - rhel9cis_rule_1_1_2_2_1 + tags: + - level1-server + - level1-workstation + - audit + - mounts + - rule_1.1.2.2.1 + vars: + warn_control_id: '1.1.2.2.1' + block: + - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | check exists" + ansible.builtin.shell: mount -l | grep -w /dev/shm + changed_when: false + register: rhel9cis_1_8_1_1_mount_check + + - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition" + when: rhel9cis_1_8_1_1_mount_check.rc == 1 + block: + - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + + - name: "1.1.2.2.1 | AUDIT | Ensure separate partition exists for /home | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: | + "1.1.2.2.2 | PATCH | Ensure nodev option set on /dev/shm partition + 1.1.2.2.3 | PATCH | Ensure nosuid option set on /dev/shm partition + 1.1.2.2.4 | PATCH | Ensure noexec option set on /dev/shm partition" + when: + - rhel9cis_rule_1_1_2_2_2 or + rhel9cis_rule_1_1_2_2_3 or + rhel9cis_rule_1_1_2_2_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1.1.2.2.2 + - rule_1.1.2.2.3 + - rule_1.1.2.2.4 + ansible.posix.mount: + name: /dev/shm + src: tmpfs + fstype: tmpfs + state: mounted + opts: defaults,{% if rhel9cis_rule_1_1_2_2_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_2_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_2_4 %}noexec{% endif %} + notify: Change_requires_reboot diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml new file mode 100644 index 0000000..1468135 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -0,0 +1,49 @@ +--- + +- name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home" + when: + - required_mount not in mount_names + - rhel9cis_rule_1_1_2_3_1 + tags: + - level2-server + - level2-workstation + - audit + - mounts + - rule_1_1_2.3.1 + - skip_ansible_lint + vars: + warn_control_id: '1.1.2.3.1' + required_mount: '/home' + block: + - name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + + - name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: | + "1.1.2.3.2 | PATCH | Ensure nodev option set on /home partition + 1.1.2.3.3 | PATCH | Ensure nosuid option set on /home partition" + when: + - item.mount == "/home" + - rhel9cis_rule_1_1_2_3_2 or + rhel9cis_rule_1_1_2_3_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1_1_2.3.2 + - rule_1_1_2.3.3 + ansible.builtin.mount: + name: /home + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel9cis_rule_1_1_2_3_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_3_3 %}nosuid{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + notify: Change_requires_reboot diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml new file mode 100644 index 0000000..afa754b --- /dev/null +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -0,0 +1,49 @@ +--- + +- name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var" + when: + - required_mount not in mount_names + - rhel9cis_rule_1_1_2_4_1 + tags: + - level2-server + - level2-workstation + - patch + - mounts + - rule_1_1_2.4.1 + vars: + warn_control_id: '1.1.2.4.1' + required_mount: '/var' + block: + - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + + - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +# skips if mount is absent +- name: | + "1.1.2.4.2 | PATCH | Ensure nodev option set on /var partition" + "1.1.2.4.3 | PATCH | Ensure nosuid option set on /var partition" + when: + - item.mount == "/var" + - rhel9cis_rule_1_1_2_4_2 or + rhel9cis_rule_1_1_2_4_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1_1_2.4.2 + - rule_1_1_2.4.3 + ansible.builtin.mount: + name: /var + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel9cis_rule_1_1_2_4_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_4_3 %}nosuid{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + notify: Change_requires_reboot diff --git a/tasks/section_1/cis_1.1.2.5.x.yml b/tasks/section_1/cis_1.1.2.5.x.yml new file mode 100644 index 0000000..93fa27c --- /dev/null +++ b/tasks/section_1/cis_1.1.2.5.x.yml @@ -0,0 +1,53 @@ +--- + +# Skips if mount is absent +- name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp" + when: + - required_mount not in mount_names + - rhel9cis_rule_1_1_2_5_1 + tags: + - level2-server + - level2-workstation + - audit + - mounts + - rule_1_1_2.5.1 + vars: + warn_control_id: '1.1.2.5.1' + required_mount: '/var/tmp' + block: + - name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + + - name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +# skips if mount is absent +- name: | + "1.1.2.5.2 | PATCH | Ensure nodev option set on /var/tmp partition" + "1.1.2.5.3 | PATCH | Ensure nosuid option set on /var/tmp partition" + "1.1.2.5.4 | PATCH | Ensure noexec option set on /var/tmp partition" + when: + - item.mount == "/var/tmp" + - rhel9cis_rule_1_1_2_5_2 or + rhel9cis_rule_1_1_2_5_3 or + rhel9cis_rule_1_1_2_5_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1_1_2.5.2 + - rule_1_1_2.5.3 + - rule_1_1_2.5.4 + ansible.builtin.mount: + name: /var/tmp + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel9cis_rule_1_1_2_5_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_5_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_5_4 %}noexec{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + notify: Change_requires_reboot diff --git a/tasks/section_1/cis_1.1.2.6.x.yml b/tasks/section_1/cis_1.1.2.6.x.yml new file mode 100644 index 0000000..6b497ec --- /dev/null +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -0,0 +1,51 @@ +--- + +- name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log" + when: + - required_mount not in mount_names + - rhel9cis_rule_1_1_2_6_1 + tags: + - level2-server + - level2-workstation + - audit + - mounts + - rule_1_1_2.6.1 + vars: + warn_control_id: '1.1.2.6.1' + required_mount: '/var/log' + block: + - name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + + - name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: | + "1.1.2.6.2 | PATCH | Ensure nodev option set on /var/log partition" + "1.1.2.6.3 | PATCH | Ensure nosuid option set on /var/log partition" + "1.1.2.6.4 | PATCH | Ensure noexec option set on /var/log partition" + when: + - item.mount == "/var/log" + - rhel9cis_rule_1_1_2_6_2 or + rhel9cis_rule_1_1_2_6_3 or + rhel9cis_rule_1_1_2_6_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1_1_2.6.2 + - rule_1_1_2.6.3 + - rule_1_1_2.6.4 + ansible.builtin.mount: + name: /var/log + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel9cis_rule_1_1_2_6_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_6_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_6_4 %}noexec{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + notify: Change_requires_reboot diff --git a/tasks/section_1/cis_1.1.2.7.x.yml b/tasks/section_1/cis_1.1.2.7.x.yml new file mode 100644 index 0000000..6b5d760 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -0,0 +1,51 @@ +--- + +- name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit" + when: + - required_mount not in mount_names + - rhel9cis_rule_1_1_2_7_1 + tags: + - level2-server + - level2-workstation + - audit + - mounts + - rule_1_1_2.7.1 + vars: + warn_control_id: '1.1.2.7.1' + required_mount: '/var/log/audit' + block: + - name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + + - name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: | + "1.1.2.7.2 | PATCH | Ensure nodev option set on /var/log/audit partition" + "1.1.2.7.3 | PATCH | Ensure nosuid option set on /var/log/audit partition" + "1.1.2.7.4 | PATCH | Ensure noexec option set on /var/log/audit partition" + ansible.builtin.mount: + name: /var/log/audit + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel9cis_rule_1_1_2_7_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_7_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_7_4 %}noexec{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + notify: Change_requires_reboot + when: + - item.mount == "/var/log/audit" + - rhel9cis_rule_1_1_2_7_2 or + rhel9cis_rule_1_1_2_7_3 or + rhel9cis_rule_1_1_2_7_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1_1_2.7.2 + - rule_1_1_2.7.3 + - rule_1_1_2.7.4 diff --git a/tasks/section_1/cis_1.1.2.x.yml b/tasks/section_1/cis_1.1.2.x.yml deleted file mode 100644 index 10d6d2d..0000000 --- a/tasks/section_1/cis_1.1.2.x.yml +++ /dev/null @@ -1,82 +0,0 @@ ---- - -- name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition" - block: - - name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - - - name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '1.1.2.1' - required_mount: '/tmp' - when: - - required_mount not in mount_names - - rhel9cis_rule_1_1_2_1 - tags: - - level1-server - - level1-workstation - - audit - - mounts - - rule_1.1.2.1 - -# via fstab -- name: | - "1.1.2.2 | PATCH | Ensure nodev option set on /tmp partition" - "1.1.2.3 | PATCH | Ensure noexec option set on /tmp partition" - "1.1.2.4 | PATCH | Ensure nosuid option set on /tmp partition" - ansible.posix.mount: - name: /tmp - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel9cis_rule_1_1_2_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_2_4 %}nosuid{% endif %} - notify: Remount tmp - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - when: - - item.mount == "/tmp" - - not rhel9cis_tmp_svc - - rhel9cis_rule_1_1_2_2 or - rhel9cis_rule_1_1_2_3 or - rhel9cis_rule_1_1_2_4 - tags: - - level1-server - - level1-workstation - - patch - - mounts - - rule_1.1.2.2 - - rule_1.1.2.3 - - rule_1.1.2.4 - -# via systemd -- name: | - "1.1.2.1 | PATCH | Ensure /tmp is configured" - "1.1.2.2 | PATCH | Ensure nodev option set on /tmp partition" - "1.1.2.3 | PATCH | Ensure noexec option set on /tmp partition" - "1.1.2.4 | PATCH | Ensure nosuid option set on /tmp partition" - ansible.builtin.template: - src: etc/systemd/system/tmp.mount.j2 - dest: /etc/systemd/system/tmp.mount - owner: root - group: root - mode: '0644' - notify: Systemd restart tmp.mount - when: - - rhel9cis_tmp_svc - - rhel9cis_rule_1_1_2_1 or - rhel9cis_rule_1_1_2_2 or - rhel9cis_rule_1_1_2_3 or - rhel9cis_rule_1_1_2_4 - tags: - - level1-server - - level1-workstation - - patch - - mounts - - rule_1.1.2.1 - - rule_1.1.2.2 - - rule_1.1.2.3 - - rule_1.1.2.4 diff --git a/tasks/section_1/cis_1.1.3.x.yml b/tasks/section_1/cis_1.1.3.x.yml deleted file mode 100644 index 3a64a06..0000000 --- a/tasks/section_1/cis_1.1.3.x.yml +++ /dev/null @@ -1,50 +0,0 @@ ---- - -- name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var" - block: - - name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - - - name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '1.1.3.1' - required_mount: '/var' - when: - - required_mount not in mount_names - - rhel9cis_rule_1_1_3_1 - tags: - - level2-server - - level2-workstation - - patch - - mounts - - rule_1.1.3.1 - -# skips if mount is absent -- name: | - "1.1.3.2 | PATCH | Ensure nodev option set on /var partition" - "1.1.3.3 | PATCH | Ensure nosuid option set on /var partition" - ansible.builtin.mount: - name: /var - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel9cis_rule_1_1_3_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_3_3 %}nosuid{% endif %} - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot - when: - - item.mount == "/var" - - rhel9cis_rule_1_1_3_2 or - rhel9cis_rule_1_1_3_3 - tags: - - level1-server - - level1-workstation - - patch - - mounts - - skip_ansible_lint - - rule_1.1.3.2 - - rule_1.1.3.3 diff --git a/tasks/section_1/cis_1.1.4.x.yml b/tasks/section_1/cis_1.1.4.x.yml deleted file mode 100644 index 713dba6..0000000 --- a/tasks/section_1/cis_1.1.4.x.yml +++ /dev/null @@ -1,54 +0,0 @@ ---- - -# Skips if mount is absent -- name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp" - block: - - name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - - - name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '1.1.4.1' - required_mount: '/var/tmp' - when: - - required_mount not in mount_names - - rhel9cis_rule_1_1_4_1 - tags: - - level2-server - - level2-workstation - - audit - - mounts - - rule_1.1.4.1 - -# skips if mount is absent -- name: | - "1.1.4.2 | PATCH | Ensure noexec option set on /var/tmp partition" - "1.1.4.3 | PATCH | Ensure nosuid option set on /var/tmp partition" - "1.1.4.4 | PATCH | Ensure nodev option set on /var/tmp partition" - ansible.builtin.mount: - name: /var/tmp - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel9cis_rule_1_1_4_2 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_4_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_4_4 %}nodev{% endif %} - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot - when: - - item.mount == "/var/tmp" - - rhel9cis_rule_1_1_4_2 or - rhel9cis_rule_1_1_4_3 or - rhel9cis_rule_1_1_4_4 - tags: - - level1-server - - level1-workstation - - patch - - mounts - - skip_ansible_lint - - rule_1.1.4.2 - - rule_1.1.4.3 - - rule_1.1.4.4 diff --git a/tasks/section_1/cis_1.1.5.x.yml b/tasks/section_1/cis_1.1.5.x.yml deleted file mode 100644 index ac8b827..0000000 --- a/tasks/section_1/cis_1.1.5.x.yml +++ /dev/null @@ -1,54 +0,0 @@ ---- - -- name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log" - block: - - name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - - - name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml - - vars: - warn_control_id: '1.1.5.1' - required_mount: '/var/log' - when: - - required_mount not in mount_names - - rhel9cis_rule_1_1_5_1 - tags: - - level2-server - - level2-workstation - - audit - - mounts - - rule_1.1.5.1 - - skip_ansible_lint - -- name: | - "1.1.5.2 | PATCH | Ensure nodev option set on /var/log partition" - "1.1.5.3 | PATCH | Ensure noexec option set on /var/log partition" - "1.1.5.4 | PATCH | Ensure nosuid option set on /var/log partition" - ansible.builtin.mount: - name: /var/log - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel9cis_rule_1_1_5_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_5_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_5_4 %}nosuid{% endif %} - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot - when: - - item.mount == "/var/log" - - rhel9cis_rule_1_1_5_2 or - rhel9cis_rule_1_1_5_3 or - rhel9cis_rule_1_1_5_4 - tags: - - level1-server - - level1-workstation - - patch - - mounts - - skip_ansible_lint - - rule_1.1.5.2 - - rule_1.1.5.3 - - rule_1.1.5.4 diff --git a/tasks/section_1/cis_1.1.6.x.yml b/tasks/section_1/cis_1.1.6.x.yml deleted file mode 100644 index 5a7c8f4..0000000 --- a/tasks/section_1/cis_1.1.6.x.yml +++ /dev/null @@ -1,53 +0,0 @@ ---- - -- name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit" - block: - - name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - - - name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml - - vars: - warn_control_id: '1.1.6.1' - required_mount: '/var/log/audit' - when: - - required_mount not in mount_names - - rhel9cis_rule_1_1_6_1 - tags: - - level2-server - - level2-workstation - - audit - - mounts - - rule_1.1.6.1 - -- name: | - "1.1.6.2 | PATCH | Ensure noexec option set on /var/log/audit partition" - "1.1.6.3 | PATCH | Ensure nodev option set on /var/log/audit partition" - "1.1.6.4 | PATCH | Ensure nosuid option set on /var/log/audit partition" - ansible.builtin.mount: - name: /var/log/audit - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel9cis_rule_1_1_6_2 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_6_3 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_6_4 %}nosuid{% endif %} - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot - when: - - item.mount == "/var/log/audit" - - rhel9cis_rule_1_1_6_2 or - rhel9cis_rule_1_1_6_3 or - rhel9cis_rule_1_1_6_4 - tags: - - level1-server - - level1-workstation - - patch - - mounts - - skip_ansible_lint - - rule_1.1.6.2 - - rule_1.1.6.3 - - rule_1.1.6.4 diff --git a/tasks/section_1/cis_1.1.7.x.yml b/tasks/section_1/cis_1.1.7.x.yml deleted file mode 100644 index d113361..0000000 --- a/tasks/section_1/cis_1.1.7.x.yml +++ /dev/null @@ -1,51 +0,0 @@ ---- - -- name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home" - block: - - name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - - - name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml - - vars: - warn_control_id: '1.1.7.1' - required_mount: '/home' - when: - - required_mount not in mount_names - - rhel9cis_rule_1_1_7_1 - tags: - - level2-server - - level2-workstation - - audit - - mounts - - rule_1.1.7.1 - - skip_ansible_lint - -- name: | - "1.1.7.2 | PATCH | Ensure nodev option set on /home partition - 1.1.7.3 | PATCH | Ensure nosuid option set on /home partition" - ansible.builtin.mount: - name: /home - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel9cis_rule_1_1_7_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_7_3 %}nosuid{% endif %} - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot - when: - - item.mount == "/home" - - rhel9cis_rule_1_1_7_2 or - rhel9cis_rule_1_1_7_3 - tags: - - level1-server - - level1-workstation - - patch - - mounts - - rule_1.1.7.2 - - rule_1.1.7.3 - - skip_ansible_lint diff --git a/tasks/section_1/cis_1.1.8.x.yml b/tasks/section_1/cis_1.1.8.x.yml deleted file mode 100644 index 6a50de8..0000000 --- a/tasks/section_1/cis_1.1.8.x.yml +++ /dev/null @@ -1,56 +0,0 @@ ---- - -# Skips if mount is absent -- name: "1.1.8.1 | AUDIT | Ensure /dev/shm is a separate partition" - block: - - name: "1.1.8.1 | AUDIT | Ensure /dev/shm is a separate partition | check exists" - ansible.builtin.shell: mount -l | grep -w /dev/shm - changed_when: false - register: rhel9cis_1_8_1_1_mount_check - - - name: "1.1.8.1 | AUDIT | Ensure /dev/shm is a separate partition" - block: - - name: "1.1.8.1 | AUDIT | Ensure /dev/shm is a separate partition | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - - - name: "1.1.8.1 | AUDIT | Ensure separate partition exists for /home | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml - when: rhel9cis_1_8_1_1_mount_check.rc == 1 - - vars: - warn_control_id: '1.1.8.1' - when: - - rhel9cis_rule_1_1_8_1 - tags: - - level1-server - - level1-workstation - - audit - - mounts - - rule_1.1.8.1 - - skip_ansible_lint - -- name: | - "1.1.8.2 | PATCH | Ensure nodev option set on /dev/shm partition | Set nodev option - 1.1.8.3 | PATCH | Ensure noexec option set on /dev/shm partition | Set nosuid option - 1.1.8.4 | PATCH | Ensure nosuid option set on /dev/shm partition | Set noexec option" - ansible.posix.mount: - name: /dev/shm - src: tmpfs - fstype: tmpfs - state: mounted - opts: defaults,{% if rhel9cis_rule_1_1_8_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_8_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_8_4 %}nosuid{% endif %} - notify: Change_requires_reboot - when: - - rhel9cis_rule_1_1_8_2 or - rhel9cis_rule_1_1_8_3 or - rhel9cis_rule_1_1_8_4 - tags: - - level1-server - - level1-workstation - - patch - - mounts - - rule_1.1.8.2 - - rule_1.1.8.3 - - rule_1.1.8.4 diff --git a/tasks/section_1/cis_1.1.x.yml b/tasks/section_1/cis_1.1.x.yml deleted file mode 100644 index c6cde83..0000000 --- a/tasks/section_1/cis_1.1.x.yml +++ /dev/null @@ -1,36 +0,0 @@ ---- - -- name: "1.1.9 | PATCH | Disable USB Storage" - block: - - name: "1.1.9 | PATCH | Disable USB Storage | Edit modprobe config" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/CIS.conf - regexp: "^(#)?install usb-storage(\\s|$)" - line: "install usb-storage /bin/true" - create: true - owner: root - group: root - mode: '0600' - - - name: "1.1.9 | PATCH | Disable USB Storage | Edit modprobe config" - community.general.modprobe: - name: usb-storage - state: absent - when: not system_is_container - - - name: "1.1.9 | PATCH | Disable USB Storage | blacklist" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/blacklist.conf - regexp: "^(#)?blacklist usb-storage(\\s|$)" - line: "blacklist usb-storage" - create: true - mode: '0600' - when: - - rhel9cis_rule_1_1_9 - tags: - - level1-server - - level2-workstation - - patch - - mounts - - removable_storage - - rule_1.1.9 diff --git a/tasks/section_1/cis_1.10.yml b/tasks/section_1/cis_1.10.yml deleted file mode 100644 index adb25c1..0000000 --- a/tasks/section_1/cis_1.10.yml +++ /dev/null @@ -1,25 +0,0 @@ ---- - -- name: "1.10 | PATCH | Ensure system-wide crypto policy is not legacy" - block: - - name: "1.10 | PATCH | Ensure system-wide crypto policy is not legacy | set_fact" - ansible.builtin.set_fact: - rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{% if rhel9cis_crypto_policy_module | length > 0 %}:{{ rhel9cis_crypto_policy_module }}{% endif %}" - - - name: "1.10 | PATCH | Ensure system-wide crypto policy is not legacy" - ansible.builtin.shell: | - update-crypto-policies --set "{{ rhel9cis_full_crypto_policy }}" - update-crypto-policies - notify: Change_requires_reboot - when: - - rhel9cis_system_wide_crypto_policy.stdout != rhel9cis_full_crypto_policy - when: - - rhel9cis_rule_1_10 - - tags: - - level1-server - - level1-workstation - - automated - - no system_is_ec2 - - patch - - rule_1.10 diff --git a/tasks/section_1/cis_1.2.1.x.yml b/tasks/section_1/cis_1.2.1.x.yml new file mode 100644 index 0000000..8e805ab --- /dev/null +++ b/tasks/section_1/cis_1.2.1.x.yml @@ -0,0 +1,121 @@ +--- + +- name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured" + when: + - rhel9cis_rule_1_2_1_1 + - ansible_facts.distribution == "RedHat" or + ansible_facts.distribution == "Rocky" or + ansible_facts.distribution == "AlmaLinux" + tags: + - level1-server + - level1-workstation + - manual + - patch + - rule_1.2.1.1 + block: + - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | list installed pubkey keys" + ansible.builtin.shell: "rpm -qa | grep {{ os_gpg_key_pubkey_name }}" + changed_when: false + failed_when: false + register: os_installed_pub_keys + + - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | Query found keys" + ansible.builtin.shell: 'rpm -q --queryformat "%{PACKAGER} %{VERSION}\\n" {{ os_gpg_key_pubkey_name }} | grep "{{ os_gpg_key_pubkey_content }}"' + changed_when: false + failed_when: false + register: os_gpg_key_check + when: os_installed_pub_keys.rc == 0 + + - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | expected keys fail" + when: + - os_installed_pub_keys.rc == 1 or + os_gpg_key_check.rc == 1 + ansible.builtin.fail: + msg: Installed GPG Keys do not meet expected values or expected keys are not installed + +- name: "1.2.1.2 | PATCH | Ensure gpgcheck is globally activated" + when: + - rhel9cis_rule_1_2_1_2 + tags: + - level1-server + - level1-workstation + - patch + - rule_1.2.1.2 + block: + - name: "1.2.1.2 | AUDIT | Ensure gpgcheck is globally activated | Find repos" + ansible.builtin.find: + paths: /etc/yum.repos.d + patterns: "*.repo" + register: yum_repos + + - name: "1.2.1.2 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos" + ansible.builtin.replace: + name: "{{ item.path }}" + regexp: "^gpgcheck=0" + replace: "gpgcheck=1" + loop: "{{ yum_repos.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "1.2.1.3 | AUDIT | Ensure repo_gpgcheck is globally activated" + when: + - rhel9cis_rule_1_2_1_3 + - rhel9cis_rule_enable_repogpg + - not rhel9cis_rhel_default_repo + tags: + - level1-server + - level1-workstation + - manual + - audit + - rule_1.2.1.3 + block: + - name: "1.2.1.3 | PATCH | Ensure repo_gpgcheck is globally activated | dnf.conf" + ansible.builtin.lineinfile: + path: /etc/dnf/dnf.conf + regexp: '^repo_gpgcheck' + line: repo_gpgcheck=1 + + - name: "1.2.1.3 | AUDIT| Ensure repo_gpgcheck is globally activated | get repo files" + ansible.builtin.find: + paths: /etc/yum.repos.d + patterns: "*.repo" + register: repo_files + + - name: "1.2.1.3 | PATCH | Ensure repo_gpgcheck is globally activated | amend repo files" + ansible.builtin.replace: + path: "{{ item.path }}" + regexp: '^repo_gpgcheck( |)=( |)0' + replace: repo_gpgcheck=1 + loop: "{{ repo_files.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "1.2.1.4 | AUDIT | Ensure package manager repositories are configured" + when: + - rhel9cis_rule_1_2_1_4 + tags: + - level1-server + - level1-workstation + - manual + - audit + - rule_1.2.1.4 + - skip_ansible_lint + vars: + warn_control_id: '1.2.1.4' + block: + - name: "1.2.1.4 | AUDIT | Ensure package manager repositories are configured | Get repo list" + ansible.builtin.shell: dnf repolist + changed_when: false + failed_when: false + register: dnf_configured + check_mode: false + + - name: "1.2.1.4 | AUDIT | Ensure package manager repositories are configured | Display repo list" + ansible.builtin.debug: + msg: + - "Warning!! Below are the configured repos. Please review and make sure all align with site policy" + - "{{ dnf_configured.stdout_lines }}" + + - name: "1.2.1.4 | AUDIT | Ensure package manager repositories are configured | Warn Count" + ansible.builtin.import_tasks: + file: warning_facts.yml diff --git a/tasks/section_1/cis_1.9.yml b/tasks/section_1/cis_1.2.2.x.yml similarity index 60% rename from tasks/section_1/cis_1.9.yml rename to tasks/section_1/cis_1.2.2.x.yml index e226948..7c6dff7 100644 --- a/tasks/section_1/cis_1.9.yml +++ b/tasks/section_1/cis_1.2.2.x.yml @@ -1,16 +1,16 @@ --- -- name: "1.9 | PATCH | Ensure updates, patches, and additional security software are installed" +- name: "1.2.2.1 | PATCH | Ensure updates, patches, and additional security software are installed" ansible.builtin.package: name: "*" state: latest notify: Change_requires_reboot when: - - rhel9cis_rule_1_9 + - rhel9cis_rule_1_2_2_1 - not system_is_ec2 tags: - level1-server - level1-workstation - patch - - rule_1.9 + - rule_1.2.2.1 - skip_ansible_lint diff --git a/tasks/section_1/cis_1.2.x.yml b/tasks/section_1/cis_1.2.x.yml deleted file mode 100644 index fc0bf27..0000000 --- a/tasks/section_1/cis_1.2.x.yml +++ /dev/null @@ -1,122 +0,0 @@ ---- - -- name: "1.2.1 | AUDIT | Ensure GPG keys are configured" - block: - - name: "1.2.1 | AUDIT | Ensure GPG keys are configured | list installed pubkey keys" - ansible.builtin.shell: "rpm -qa | grep {{ os_gpg_key_pubkey_name }}" - changed_when: false - failed_when: false - register: os_installed_pub_keys - - - name: "1.2.1 | AUDIT | Ensure GPG keys are configured | Query found keys" - ansible.builtin.shell: 'rpm -q --queryformat "%{PACKAGER} %{VERSION}\\n" {{ os_gpg_key_pubkey_name }} | grep "{{ os_gpg_key_pubkey_content }}"' - changed_when: false - failed_when: false - register: os_gpg_key_check - when: os_installed_pub_keys.rc == 0 - - - name: "1.2.1 | AUDIT | Ensure GPG keys are configured | expected keys fail" - ansible.builtin.fail: - msg: Installed GPG Keys do not meet expected values or expected keys are not installed - when: - - os_installed_pub_keys.rc == 1 or - os_gpg_key_check.rc == 1 - when: - - rhel9cis_rule_1_2_1 - - ansible_facts.distribution == "RedHat" or - ansible_facts.distribution == "Rocky" or - ansible_facts.distribution == "AlmaLinux" - tags: - - level1-server - - level1-workstation - - manual - - patch - - rule_1.2.1 - -- name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated" - block: - - name: "1.2.2 | AUDIT | Ensure gpgcheck is globally activated | Find repos" - ansible.builtin.find: - paths: /etc/yum.repos.d - patterns: "*.repo" - register: yum_repos - - - name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos" - ansible.builtin.replace: - name: "{{ item.path }}" - regexp: "^gpgcheck=0" - replace: "gpgcheck=1" - loop: "{{ yum_repos.files }}" - loop_control: - label: "{{ item.path }}" - when: - - rhel9cis_rule_1_2_2 - tags: - - level1-server - - level1-workstation - - patch - - rule_1.2.2 - -- name: "1.2.3 | AUDIT | Ensure package manager repositories are configured" - block: - - name: "1.2.3 | AUDIT | Ensure package manager repositories are configured | Get repo list" - ansible.builtin.shell: dnf repolist - changed_when: false - failed_when: false - register: dnf_configured - check_mode: false - - - name: "1.2.3 | AUDIT | Ensure package manager repositories are configured | Display repo list" - ansible.builtin.debug: - msg: - - "Warning!! Below are the configured repos. Please review and make sure all align with site policy" - - "{{ dnf_configured.stdout_lines }}" - - - name: "1.2.3 | AUDIT | Ensure package manager repositories are configured | Warn Count" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '1.2.3' - when: - - rhel9cis_rule_1_2_3 - tags: - - level1-server - - level1-workstation - - manual - - audit - - rule_1.2.3 - - skip_ansible_lint - -- name: "1.2.4 | AUDIT | Ensure repo_gpgcheck is globally activated" - block: - - name: "1.2.4 | PATCH | Ensure repo_gpgcheck is globally activated | dnf.conf" - ansible.builtin.lineinfile: - path: /etc/dnf/dnf.conf - regexp: '^repo_gpgcheck' - line: repo_gpgcheck=1 - - - name: "1.2.4 | AUDIT| Ensure repo_gpgcheck is globally activated | get repo files" - ansible.builtin.find: - paths: /etc/yum.repos.d - patterns: "*.repo" - register: repo_files - - - name: "1.2.4 | PATCH | Ensure repo_gpgcheck is globally activated | amend repo files" - ansible.builtin.replace: - path: "{{ item.path }}" - regexp: '^repo_gpgcheck( |)=( |)0' - replace: repo_gpgcheck=1 - loop: "{{ repo_files.files }}" - loop_control: - label: "{{ item.path }}" - - when: - - rhel9cis_rule_1_2_4 - - rhel9cis_rule_enable_repogpg - - not rhel9cis_rhel_default_repo - tags: - - level1-server - - level1-workstation - - manual - - audit - - rule_1.2.4 diff --git a/tasks/section_1/cis_1.3.1.x.yml b/tasks/section_1/cis_1.3.1.x.yml new file mode 100644 index 0000000..2e0f0ce --- /dev/null +++ b/tasks/section_1/cis_1.3.1.x.yml @@ -0,0 +1,136 @@ +--- + +- name: "1.3.1.1 | PATCH | Ensure SELinux is installed" + when: + - rhel9cis_rule_1_3_1_1 + - not rhel9cis_selinux_disable + tags: + - level1-server + - level1-workstation + - patch + - rule_1.3.1.1 + ansible.builtin.package: + name: libselinux + state: present + +- name: "1.3.1.2 | PATCH | Ensure SELinux is not disabled in bootloader configuration" + when: + - rhel9cis_rule_1_3_1_2 + - not rhel9cis_selinux_disable + tags: + - level1-server + - level1-workstation + - scored + - patch + - rule_1.3.1.2 + ansible.builtin.replace: + path: /etc/default/grub + regexp: '{{ item }}' + replace: '' + loop: + - selinux=0 + - enforcing=0 + register: selinux_grub_patch + ignore_errors: true # noqa ignore-errors + notify: Grub2cfg + +# State set to enforcing because control 1.3.1.5 requires enforcing to be set +- name: "1.3.1.3 | PATCH | Ensure SELinux policy is configured" + when: + - rhel9cis_rule_1_3_1_3 + - not rhel9cis_selinux_disable + tags: + - level1-server + - level1-workstation + - selinux + - patch + - rule_1.3.1.3 + ansible.posix.selinux: + conf: /etc/selinux/config + policy: "{{ rhel9cis_selinux_pol }}" + state: "{{ rhel9cis_selinux_enforce }}" + +- name: "1.3.1.4 | PATCH | Ensure the SELinux state is not disabled" + when: + - rhel9cis_rule_1_3_1_4 + - not rhel9cis_selinux_disable + tags: + - level1-server + - level1-workstation + - selinux + - patch + - rule_1.3.1.4 + ansible.posix.selinux: + conf: /etc/selinux/config + policy: "{{ rhel9cis_selinux_pol }}" + state: "{{ rhel9cis_selinux_enforce }}" + +- name: "1.3.1.5 | PATCH | Ensure the SELinux state is enforcing" + when: + - rhel9cis_selinux_enforce == 'enforcing' + - rhel9cis_rule_1_3_1_5 + - not rhel9cis_selinux_disable + tags: + - level2-server + - level2-workstation + - selinux + - patch + - rule_1.3.1.5 + ansible.posix.selinux: + conf: /etc/selinux/config + policy: "{{ rhel9cis_selinux_pol }}" + state: enforcing + +- name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist" + when: + - rhel9cis_rule_1_3_1_6 + - not rhel9cis_selinux_disable + tags: + - level1-server + - level1-workstation + - audit + - services + - rule_1.3.1.6 + vars: + 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 }' + register: rhelcis_1_3_1_6_unconf_services + failed_when: false + changed_when: false + + - name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist | Message on unconfined services" + when: rhelcis_1_3_1_6_unconf_services.stdout | length > 0 + ansible.builtin.debug: + msg: "Warning!! You have unconfined services: {{ rhelcis_1_3_1_6_unconf_services.stdout_lines }}" + + - name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist | warning count" + when: rhelcis_1_3_1_6_unconf_services.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "1.3.1.7 | PATCH | Ensure the MCS Translation Service (mcstrans) is not installed" + when: + - rhel9cis_rule_1_3_1_7 + tags: + - level1-server + - level1-workstation + - patch + - rule_1.3.1.7 + ansible.builtin.package: + name: mcstrans + state: absent + +- name: "1.3.1.8 | PATCH | Ensure SETroubleshoot is not installed" + ansible.builtin.package: + name: setroubleshoot + state: absent + when: + - rhel9cis_rule_1_3_1_8 + - "'setroubleshoot' in ansible_facts.packages" + tags: + - level1-server + - selinux + - patch + - rule_1.3.1.8 diff --git a/tasks/section_1/cis_1.3.x.yml b/tasks/section_1/cis_1.3.x.yml_AIDE similarity index 100% rename from tasks/section_1/cis_1.3.x.yml rename to tasks/section_1/cis_1.3.x.yml_AIDE diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index dd8d83f..384ab24 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -1,44 +1,43 @@ --- - name: "1.4.1 | PATCH | Ensure bootloader password is set" - ansible.builtin.copy: - dest: /boot/grub2/user.cfg - content: "GRUB2_PASSWORD={{ rhel9cis_bootloader_password_hash }}" # noqa template-instead-of-copy - owner: root - group: root - mode: '0600' - notify: Grub2cfg when: - - rhel9cis_set_boot_pass - - rhel9cis_rule_1_4_1 + - rhel9cis_set_boot_pass + - rhel9cis_rule_1_4_1 tags: - - level1-server - - level1-workstation - - grub - - patch - - rule_1.4.1 + - level1-server + - level1-workstation + - grub + - patch + - rule_1.4.1 + ansible.builtin.copy: + dest: /boot/grub2/user.cfg + content: "GRUB2_PASSWORD={{ rhel9cis_bootloader_password_hash }}" # noqa template-instead-of-copy + owner: root + group: root + mode: '0600' + notify: Grub2cfg - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured" - block: - - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured" - ansible.builtin.file: - path: "/boot/grub2/{{ item.path }}" - owner: root - group: root - mode: "{{ item.mode }}" - state: touch - modification_time: preserve - access_time: preserve - loop: - - { path: 'grub.cfg', mode: '0700' } - - { path: 'grubenv', mode: '0600' } - - { path: 'user.cfg', mode: '0600' } - when: - - rhel9cis_rule_1_4_2 + - rhel9cis_rule_1_4_2 tags: - - level1-server - - level1-workstation - - grub - - patch - - rule_1.4.2 + - level1-server + - level1-workstation + - grub + - patch + - rule_1.4.2 + block: + - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured" + ansible.builtin.file: + path: "/boot/grub2/{{ item.path }}" + owner: root + group: root + mode: "{{ item.mode }}" + state: touch + modification_time: preserve + access_time: preserve + loop: + - { path: 'grub.cfg', mode: '0700' } + - { path: 'grubenv', mode: '0600' } + - { path: 'user.cfg', mode: '0600' } diff --git a/tasks/section_1/cis_1.5.x.yml b/tasks/section_1/cis_1.5.x.yml index 3f80647..b8ea0dd 100644 --- a/tasks/section_1/cis_1.5.x.yml +++ b/tasks/section_1/cis_1.5.x.yml @@ -1,48 +1,66 @@ --- -- name: "1.5.1 | PATCH | Ensure core dump storage is disabled" - ansible.builtin.lineinfile: - path: /etc/systemd/coredump.conf - regexp: '^Storage\s*=\s*(?!none).*' - line: 'Storage=none' - notify: Systemd daemon reload +- name: "1.5.1 | PATCH | Ensure address space layout randomization (ASLR) is enabled" when: - - rhel9cis_rule_1_5_1 - - systemd_coredump.stat.exists + - rhel9cis_rule_1_5_1 tags: - - level1-server - - level1-workstation - - patch - - rule_1.5.1 - -- name: "1.5.2 | PATCH | Ensure core dump backtraces are disabled" - ansible.builtin.lineinfile: - path: /etc/systemd/coredump.conf - regexp: '^ProcessSizeMax\s*=\s*.*[1-9]$' - line: 'ProcessSizeMax=0' - when: - - rhel9cis_rule_1_5_2 - tags: - - level1-server - - level1-workstation - - patch - - sysctl - - rule_1.5.2 - -- name: "1.5.3 | PATCH | Ensure address space layout randomization (ASLR) is enabled" + - level1-server + - level1-workstation + - patch + - sysctl + - rule_1.5.1 block: - - name: "1.5.3 | PATCH | Ensure address space layout randomization (ASLR) is enabled" - ansible.builtin.set_fact: - rhel9cis_sysctl_update: true + - name: "1.5.1 | PATCH | Ensure address space layout randomization (ASLR) is enabled" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true - - name: "1.5.3 | PATCH | Ensure address space layout randomization (ASLR) is enabled" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-kernel_sysctl.conf" + - name: "1.5.1 | PATCH | Ensure address space layout randomization (ASLR) is enabled" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-kernel_sysctl.conf" + +- name: "1.5.2 | PATCH | Ensure ptrace_scope is restricted" when: - - rhel9cis_rule_1_5_3 + - rhel9cis_rule_1_5_2 tags: - - level1-server - - level1-workstation - - patch - - sysctl - - rule_1.5.3 + - level1-server + - level1-workstation + - patch + - sysctl + - rule_1.5.2 + block: + - name: "1.5.2 | PATCH | Ensure ptrace_scope is restricted" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true + + - name: "1.5.2 | PATCH | Ensure ptrace_scope is restricted" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-kernel_sysctl.conf" + +- name: "1.5.3 | PATCH | Ensure core dump backtraces are disabled" + when: + - rhel9cis_rule_1_5_3 + tags: + - level1-server + - level1-workstation + - patch + - sysctl + - rule_1.5.3 + ansible.builtin.lineinfile: + path: /etc/systemd/coredump.conf + regexp: '^ProcessSizeMax\s*=\s*.*[1-9]$' + line: 'ProcessSizeMax=0' + +- name: "1.5.4 | PATCH | Ensure core dump storage is disabled" + when: + - rhel9cis_rule_1_5_4 + - systemd_coredump.stat.exists + tags: + - level1-server + - level1-workstation + - patch + - rule_1.5.4 + ansible.builtin.lineinfile: + path: /etc/systemd/coredump.conf + regexp: '^Storage\s*=\s*(?!none).*' + line: 'Storage=none' + notify: Systemd daemon reload diff --git a/tasks/section_1/cis_1.6.1.x.yml b/tasks/section_1/cis_1.6.1.x.yml deleted file mode 100644 index 7ca0fd1..0000000 --- a/tasks/section_1/cis_1.6.1.x.yml +++ /dev/null @@ -1,130 +0,0 @@ ---- - -- name: "1.6.1.1 | PATCH | Ensure SELinux is installed" - ansible.builtin.package: - name: libselinux - state: present - when: - - rhel9cis_rule_1_6_1_1 - tags: - - level1-server - - level1-workstation - - patch - - rule_1.6.1.1 - -- name: "1.6.1.2 | PATCH | Ensure SELinux is not disabled in bootloader configuration" - ansible.builtin.replace: - path: /etc/default/grub - regexp: '{{ item }}' - replace: '' - loop: - - selinux=0 - - enforcing=0 - register: selinux_grub_patch - ignore_errors: true # noqa ignore-errors - notify: Grub2cfg - when: - - rhel9cis_rule_1_6_1_2 - tags: - - level1-server - - level1-workstation - - scored - - patch - - rule_1.6.1.2 - -# State set to enforcing because control 1.6.1.5 requires enforcing to be set -- name: "1.6.1.3 | PATCH | Ensure SELinux policy is configured" - ansible.posix.selinux: - conf: /etc/selinux/config - policy: "{{ rhel9cis_selinux_pol }}" - state: "{{ rhel9cis_selinux_enforce }}" - when: - - rhel9cis_rule_1_6_1_3 - tags: - - level1-server - - level1-workstation - - selinux - - patch - - rule_1.6.1.3 - -- name: "1.6.1.4 | PATCH | Ensure the SELinux state is not disabled" - ansible.posix.selinux: - conf: /etc/selinux/config - policy: "{{ rhel9cis_selinux_pol }}" - state: "{{ rhel9cis_selinux_enforce }}" - when: - - rhel9cis_rule_1_6_1_4 - tags: - - level1-server - - level1-workstation - - selinux - - patch - - rule_1.6.1.4 - -- name: "1.6.1.5 | PATCH | Ensure the SELinux state is enforcing" - ansible.posix.selinux: - conf: /etc/selinux/config - policy: "{{ rhel9cis_selinux_pol }}" - state: enforcing - when: - - rhel9cis_selinux_enforce == 'enforcing' - - rhel9cis_rule_1_6_1_5 - tags: - - level2-server - - level2-workstation - - selinux - - patch - - rule_1.6.1.5 - -- name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist" - block: - - name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist | Find the unconfined services" - ansible.builtin.shell: ps -eZ | grep unconfined_service_t | egrep -vw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }' - register: rhelcis_1_6_1_6_unconf_services - failed_when: false - changed_when: false - - - name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist | Message on unconfined services" - ansible.builtin.debug: - msg: "Warning!! You have unconfined services: {{ rhelcis_1_6_1_6_unconf_services.stdout_lines }}" - when: rhelcis_1_6_1_6_unconf_services.stdout | length > 0 - - - name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist | warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml - when: rhelcis_1_6_1_6_unconf_services.stdout | length > 0 - vars: - warn_control_id: '1.6.1.6' - when: - - rhel9cis_rule_1_6_1_6 - tags: - - level1-server - - level1-workstation - - audit - - services - - rule_1.6.1.6 - -- name: "1.6.1.7 | PATCH | Ensure SETroubleshoot is not installed" - ansible.builtin.package: - name: setroubleshoot - state: absent - when: - - rhel9cis_rule_1_6_1_7 - - "'setroubleshoot' in ansible_facts.packages" - tags: - - level1-server - - selinux - - patch - - rule_1.6.1.7 - -- name: "1.6.1.8 | PATCH | Ensure the MCS Translation Service (mcstrans) is not installed" - ansible.builtin.package: - name: mcstrans - state: absent - when: - - rhel9cis_rule_1_6_1_8 - tags: - - level1-server - - level1-workstation - - patch - - rule_1.6.1.8 diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml new file mode 100644 index 0000000..bc15fbb --- /dev/null +++ b/tasks/section_1/cis_1.6.x.yml @@ -0,0 +1,163 @@ +--- + +- name: "1.6.1 | AUDIT | Ensure system-wide crypto policy is not legacy" + when: + - rhel9cis_rule_1_6_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.6.1 + ansible.builtin.debug: + msg: "Captured in prelim to ensure not LEGACY. Runs handler to update" + changed_when: true + notify: + - Update Crypto Policy + - Set Crypto Policy + +- name: "1.6.2 | PATCH | Ensure system wide crypto policy is not set in sshd configuration" + when: + - rhel9cis_rule_1_6_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.6.2 + ansible.builtin.lineinfile: + path: /etc/sysconfig/sshd + regexp: ^CRYPTO_POLICY\s*= + state: absent + notify: Restart sshd + +- name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support" + when: + - rhel9cis_rule_1_6_3 + - "'NO-SHA1' not in rhel9cis_crypto_policy_module" + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.6.3 + block: + - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | 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: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SHA1' }}" + +- name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits" + when: + - rhel9cis_rule_1_6_4 + - "'NO-WEAKMAC' not in rhel9cis_crypto_policy_module" + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.6.4 + block: + - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-WEAKMAC' }}" + + +- name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh" + when: + - rhel9cis_rule_1_6_5 + - "'NO-SSHCBC' not in rhel9cis_crypto_policy_module" + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.6.5 + block: + - name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SSHCBC.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHCBC' }}" + +- name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh" + when: + - rhel9cis_rule_1_6_6 + - "'NO-SSHCHACHA20' not in rhel9cis_crypto_policy_module" + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.6.6 + block: + - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHCHACHA20' }}" + +- name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh" + when: + - rhel9cis_rule_1_6_7 + - "'NO-SSHETM' not in rhel9cis_crypto_policy_module" + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.6.7 + block: + - name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SSHETM.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHETM' }}" diff --git a/tasks/section_1/cis_1.7.x.yml b/tasks/section_1/cis_1.7.x.yml index 883b35b..e5ab0b4 100644 --- a/tasks/section_1/cis_1.7.x.yml +++ b/tasks/section_1/cis_1.7.x.yml @@ -1,93 +1,93 @@ --- - name: "1.7.1 | PATCH | Ensure message of the day is configured properly" - ansible.builtin.template: - src: etc/motd.j2 - dest: /etc/motd - owner: root - group: root - mode: '0644' when: - - rhel9cis_rule_1_7_1 + - rhel9cis_rule_1_7_1 tags: - - level1-server - - level1-workstation - - banner - - patch - - rule_1.7.1 + - level1-server + - level1-workstation + - banner + - patch + - rule_1.7.1 + ansible.builtin.template: + src: etc/motd.j2 + dest: /etc/motd + owner: root + group: root + mode: u-x,go-wx - name: "1.7.2 | PATCH | Ensure local login warning banner is configured properly" - ansible.builtin.template: - src: etc/issue.j2 - dest: /etc/issue - owner: root - group: root - mode: '0644' when: - - rhel9cis_rule_1_7_2 + - rhel9cis_rule_1_7_2 tags: - - level1-server - - level1-workstation - - patch - - rule_1.7.2 + - level1-server + - level1-workstation + - patch + - rule_1.7.2 + ansible.builtin.template: + src: etc/issue.j2 + dest: /etc/issue + owner: root + group: root + mode: '0644' - name: "1.7.3 | PATCH | Ensure remote login warning banner is configured properly" - ansible.builtin.template: - src: etc/issue.net.j2 - dest: /etc/issue.net - owner: root - group: root - mode: '0644' when: - - rhel9cis_rule_1_7_3 + - rhel9cis_rule_1_7_3 tags: - - level1-server - - level1-workstation - - banner - - patch - - rule_1.7.3 + - level1-server + - level1-workstation + - banner + - patch + - rule_1.7.3 + ansible.builtin.template: + src: etc/issue.net.j2 + dest: /etc/issue.net + owner: root + group: root + mode: '0644' - name: "1.7.4 | PATCH | Ensure permissions on /etc/motd are configured" - ansible.builtin.file: - path: /etc/motd - owner: root - group: root - mode: '0644' when: - - rhel9cis_rule_1_7_4 + - rhel9cis_rule_1_7_4 tags: - - level1-server - - level1-workstation - - perms - - patch - - rule_1.7.4 + - level1-server + - level1-workstation + - perms + - patch + - rule_1.7.4 + ansible.builtin.file: + path: /etc/motd + owner: root + group: root + mode: '0644' - name: "1.7.5 | PATCH | Ensure permissions on /etc/issue are configured" - ansible.builtin.file: - path: /etc/issue - owner: root - group: root - mode: '0644' when: - - rhel9cis_rule_1_7_5 + - rhel9cis_rule_1_7_5 tags: - - level1-server - - level1-workstation - - perms - - patch - - rule_1.7.5 + - level1-server + - level1-workstation + - perms + - patch + - rule_1.7.5 + ansible.builtin.file: + path: /etc/issue + owner: root + group: root + mode: '0644' - name: "1.7.6 | PATCH | Ensure permissions on /etc/issue.net are configured" - ansible.builtin.file: - path: /etc/issue.net - owner: root - group: root - mode: '0644' when: - - rhel9cis_rule_1_7_6 + - rhel9cis_rule_1_7_6 tags: - - level1-server - - level1-workstation - - perms - - patch - - rule_1.7.6 + - level1-server + - level1-workstation + - perms + - patch + - rule_1.7.6 + ansible.builtin.file: + path: /etc/issue.net + owner: root + group: root + mode: '0644' diff --git a/tasks/section_1/cis_1.8.x.yml b/tasks/section_1/cis_1.8.x.yml index ce35a48..b29aa15 100644 --- a/tasks/section_1/cis_1.8.x.yml +++ b/tasks/section_1/cis_1.8.x.yml @@ -1,264 +1,265 @@ --- - name: "1.8.1 | PATCH | Ensure GNOME Display Manager is removed" - ansible.builtin.package: - name: gdm - state: absent when: - - rhel9cis_rule_1_8_1 - - "'gdm' in ansible_facts.packages" - - not rhel9cis_gui + - rhel9cis_rule_1_8_1 + - "'gdm' in ansible_facts.packages" + - not rhel9cis_gui tags: - - level2-server - - patch - - gui - - gdm - - rule_1.8.1 + - level2-server + - patch + - gui + - gdm + - rule_1.8.1 + ansible.builtin.package: + name: gdm + state: absent - name: "1.8.2 | PATCH | Ensure GDM login banner is configured" - block: - - name: "1.8.2 | PATCH | Ensure GDM login banner is configured | gdm profile" - ansible.builtin.lineinfile: - path: /etc/dconf/profile/gdm - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - create: true - owner: root - group: root - mode: '0644' - notify: Reload dconf - loop: - - { regexp: 'user-db', line: 'user-db:user' } - - { regexp: 'system-db', line: 'system-db:gdm' } - - { regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults' } - - - name: "1.8.2 | PATCH | Ensure GDM login banner is configured | gdm profile" - ansible.builtin.template: - src: etc/dconf/db/gdm.d/01-banner-message.j2 - dest: /etc/dconf/db/gdm.d/01-banner-message - owner: root - group: root - mode: '0644' - notify: Reload dconf when: - - rhel9cis_rule_1_8_2 - - rhel9cis_gui + - rhel9cis_rule_1_8_2 + - rhel9cis_gui tags: - - level1-server - - level1-workstation - - patch - - gui - - gdm - - rule_1.8.2 + - level1-server + - level1-workstation + - patch + - gui + - gdm + - rule_1.8.2 + block: + - name: "1.8.2 | PATCH | Ensure GDM login banner is configured | gdm profile" + ansible.builtin.lineinfile: + path: /etc/dconf/profile/gdm + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + create: true + owner: root + group: root + mode: '0644' + notify: Reload dconf + loop: + - { regexp: 'user-db', line: 'user-db:user' } + - { regexp: 'system-db', line: 'system-db:gdm' } + - { regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults' } + + - name: "1.8.2 | PATCH | Ensure GDM login banner is configured | gdm profile" + ansible.builtin.template: + src: etc/dconf/db/gdm.d/01-banner-message.j2 + dest: /etc/dconf/db/gdm.d/01-banner-message + owner: root + group: root + mode: '0644' + notify: Reload dconf + - name: "1.8.3 | PATCH | Ensure GDM disable-user-list option is enabled" + when: + - rhel9cis_rule_1_8_3 + - rhel9cis_gui + tags: + - level1-server + - level1-workstation + - patch + - gui + - rule_1.8.3 ansible.builtin.lineinfile: - path: "{{ item.file }}" - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - create: true - owner: root - group: root - mode: '0644' + path: "{{ item.file }}" + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + create: true + owner: root + group: root + mode: '0644' notify: Reload dconf loop: - - { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' } - - { file: '/etc/dconf/profile/gdm', regexp: 'system-db', line: 'system-db:gdm' } - - { file: '/etc/dconf/profile/gdm', regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults'} - - { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: '\[org\/gnome\/login-screen\]', line: '[org/gnome/login-screen]' } - - { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: 'disable-user-list=', line: 'disable-user-list=true' } - when: - - rhel9cis_rule_1_8_3 - - rhel9cis_gui - tags: - - level1-server - - level1-workstation - - patch - - gui - - rule_1.8.3 + - { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' } + - { file: '/etc/dconf/profile/gdm', regexp: 'system-db', line: 'system-db:gdm' } + - { file: '/etc/dconf/profile/gdm', regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults'} + - { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: '\[org\/gnome\/login-screen\]', line: '[org/gnome/login-screen]' } + - { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: 'disable-user-list=', line: 'disable-user-list=true' } - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle" - block: - - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | User profile" - ansible.builtin.lineinfile: - path: /etc/dconf/profile/user - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - create: true - owner: root - group: root - mode: '0644' - loop: - - { regexp: '^user-db', line: 'user-db:user' } - - { regexp: '^system-db', line: 'system-db:local' } - - - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make db directory" - ansible.builtin.file: - path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d" - owner: root - group: root - mode: '0755' - state: directory - - - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make conf file" - ansible.builtin.template: - src: etc/dconf/db/00-screensaver.j2 - dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-screensaver" - owner: root - group: root - mode: '0644' - notify: Reload dconf when: - - rhel9cis_rule_1_8_4 - - rhel9cis_gui + - rhel9cis_rule_1_8_4 + - rhel9cis_gui tags: - - level1-server - - level1-workstation - - patch - - gui - - rule_1.8.4 + - level1-server + - level1-workstation + - patch + - gui + - rule_1.8.4 + block: + - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | User profile" + ansible.builtin.lineinfile: + path: /etc/dconf/profile/user + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + create: true + owner: root + group: root + mode: '0644' + loop: + - { regexp: '^user-db', line: 'user-db:user' } + - { regexp: '^system-db', line: 'system-db:local' } + + - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make db directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d" + owner: root + group: root + mode: '0755' + state: directory + + - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make conf file" + ansible.builtin.template: + src: etc/dconf/db/00-screensaver.j2 + dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-screensaver" + owner: root + group: root + mode: '0644' + notify: Reload dconf - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden" - block: - - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock directory" - ansible.builtin.file: - path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks" - owner: root - group: root - mode: '0755' - state: directory - - - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock file" - ansible.builtin.template: - src: etc/dconf/db/00-screensaver_lock.j2 - dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-screensaver" - owner: root - group: root - mode: '0644' - notify: Reload dconf when: - - rhel9cis_rule_1_8_5 - - rhel9cis_gui + - rhel9cis_rule_1_8_5 + - rhel9cis_gui tags: - - level1-server - - level1-workstation - - patch - - gui - - rule_1.8.5 + - level1-server + - level1-workstation + - patch + - gui + - rule_1.8.5 + block: + - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks" + owner: root + group: root + mode: '0755' + state: directory + + - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock file" + ansible.builtin.template: + src: etc/dconf/db/00-screensaver_lock.j2 + dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-screensaver" + owner: root + group: root + mode: '0644' + notify: Reload dconf - name: "1.8.6 | PATCH | Ensure GDM automatic mounting of removable media is disabled" - ansible.builtin.template: - src: etc/dconf/db/00-media-automount.j2 - dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-media-automount" - owner: root - group: root - mode: '0644' - notify: Reload dconf when: - - rhel9cis_rule_1_8_6 - - rhel9cis_gui + - rhel9cis_rule_1_8_6 + - rhel9cis_gui tags: - - level1-server - - level2-workstation - - patch - - gui - - rule_1.8.6 + - level1-server + - level2-workstation + - patch + - gui + - rule_1.8.6 + ansible.builtin.template: + src: etc/dconf/db/00-media-automount.j2 + dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-media-automount" + owner: root + group: root + mode: '0644' + notify: Reload dconf - name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden" - block: - - name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden | Make lock directory" - ansible.builtin.file: - path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks" - owner: root - group: root - mode: '0755' - state: directory - - - name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden | Make lock file" - ansible.builtin.template: - src: etc/dconf/db/00-automount_lock.j2 - dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-automount_lock" - owner: root - group: root - mode: '0644' - notify: Reload dconf when: - - rhel9cis_rule_1_8_7 - - rhel9cis_gui + - rhel9cis_rule_1_8_7 + - rhel9cis_gui tags: - - level1-server - - level2-workstation - - patch - - gui - - rule_1.8.7 + - level1-server + - level2-workstation + - patch + - gui + - rule_1.8.7 + block: + - name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden | Make lock directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks" + owner: root + group: root + mode: '0755' + state: directory + + - name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden | Make lock file" + ansible.builtin.template: + src: etc/dconf/db/00-automount_lock.j2 + dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-automount_lock" + owner: root + group: root + mode: '0644' + notify: Reload dconf - name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled" - block: - - name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make directory" - ansible.builtin.file: - path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d" - owner: root - group: root - mode: '0755' - state: directory - - - name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make conf file" - ansible.builtin.template: - src: etc/dconf/db/00-media-autorun.j2 - dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-media-autorun" - owner: root - group: root - mode: '0644' - notify: Reload dconf when: - - rhel9cis_rule_1_8_8 - - rhel9cis_gui + - rhel9cis_rule_1_8_8 + - rhel9cis_gui tags: - - level1-server - - level2-workstation - - patch - - gui - - rule_1.8.8 + - level1-server + - level2-workstation + - patch + - gui + - rule_1.8.8 + block: + - name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d" + owner: root + group: root + mode: '0755' + state: directory + + - name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make conf file" + ansible.builtin.template: + src: etc/dconf/db/00-media-autorun.j2 + dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-media-autorun" + owner: root + group: root + mode: '0644' + notify: Reload dconf - name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden" - block: - - name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lock directory" - ansible.builtin.file: - path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks" - owner: root - group: root - mode: '0755' - state: directory - - - name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lockfile" - ansible.builtin.template: - src: etc/dconf/db/00-autorun_lock.j2 - dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-autorun_lock" - owner: root - group: root - mode: '0644' - notify: Reload dconf when: - - rhel9cis_rule_1_8_9 - - rhel9cis_gui + - rhel9cis_rule_1_8_9 + - rhel9cis_gui tags: - - level1-server - - level2-workstation - - patch - - gui - - rule_1.8.9 + - level1-server + - level2-workstation + - patch + - gui + - rule_1.8.9 + block: + - name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lock directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks" + owner: root + group: root + mode: '0755' + state: directory + + - name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lockfile" + ansible.builtin.template: + src: etc/dconf/db/00-autorun_lock.j2 + dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-autorun_lock" + owner: root + group: root + mode: '0644' + notify: Reload dconf - name: "1.8.10 | PATCH | Ensure XDMCP is not enabled" - ansible.builtin.lineinfile: - path: /etc/gdm/custom.conf - regexp: 'Enable=true' - state: absent when: - - rhel9cis_rule_1_8_10 - - rhel9cis_gui + - rhel9cis_rule_1_8_10 + - rhel9cis_gui tags: - - level1-server - - level1-workstation - - patch - - gui - - rule_1.8.10 + - level1-server + - level1-workstation + - patch + - gui + - rule_1.8.10 + ansible.builtin.lineinfile: + path: /etc/gdm/custom.conf + regexp: 'Enable=true' + state: absent diff --git a/tasks/section_1/main.yml b/tasks/section_1/main.yml index ccc1e04..5d99f48 100644 --- a/tasks/section_1/main.yml +++ b/tasks/section_1/main.yml @@ -2,76 +2,64 @@ - name: "SECTION | 1.1.1.x | Disable unused filesystems" ansible.builtin.import_tasks: - file: cis_1.1.1.x.yml + file: cis_1.1.1.x.yml -- name: "SECTION | 1.1.2.x | Configure /tmp" +- name: "SECTION | 1.1.2.1.x | Configure /tmp" ansible.builtin.import_tasks: - file: cis_1.1.2.x.yml + file: cis_1.1.2.1.x.yml -- name: "SECTION | 1.1.3.x | Configure /var" +- name: "SECTION | 1.1.2.2.x | Configure /dev/shm" ansible.builtin.import_tasks: - file: cis_1.1.3.x.yml + file: cis_1.1.2.2.x.yml -- name: "SECTION | 1.1.4.x | Configure /var/tmp" +- name: "SECTION | 1.1.2.3.x | Configure /home" ansible.builtin.import_tasks: - file: cis_1.1.4.x.yml + file: cis_1.1.2.3.x.yml -- name: "SECTION | 1.1.5.x | Configure /var/log" +- name: "SECTION | 1.1.2.4.x | Configure /var" ansible.builtin.import_tasks: - file: cis_1.1.5.x.yml + file: cis_1.1.2.4.x.yml -- name: "SECTION | 1.1.6.x | Configure /var/log/audit" +- name: "SECTION | 1.1.2.5.x | Configure /var/tmp" ansible.builtin.import_tasks: - file: cis_1.1.6.x.yml + file: cis_1.1.2.5.x.yml -- name: "SECTION | 1.1.7.x | Configure /home" +- name: "SECTION | 1.1.2.6.x | Configure /var/log" ansible.builtin.import_tasks: - file: cis_1.1.7.x.yml + file: cis_1.1.2.6.x.yml -- name: "SECTION | 1.1.8.x | Configure /dev/shm" +- name: "SECTION | 1.1.2.7.x | Configure /var/log/audit" ansible.builtin.import_tasks: - file: cis_1.1.8.x.yml + file: cis_1.1.2.7.x.yml -- name: "SECTION | 1.1.x | Disable various mounting" +- name: "SECTION | 1.2.1.x | Configure Package Repositories" ansible.builtin.import_tasks: - file: cis_1.1.x.yml + file: cis_1.2.1.x.yml -- name: "SECTION | 1.2 | Configure Software Updates" +- name: "SECTION | 1.2.2.x | Configure Package Updates" ansible.builtin.import_tasks: - file: cis_1.2.x.yml + file: cis_1.2.2.x.yml -- name: "SECTION | 1.3 | Filesystem Integrity Checking" - ansible.builtin.import_tasks: - file: cis_1.3.x.yml - when: rhel9cis_config_aide +- name: "SECTION | 1.3.1 | Configure SELinux" + ansible.builtin.include_tasks: + file: cis_1.3.1.x.yml -- name: "SECTION | 1.4 | Secure Boot Settings" +- name: "SECTION | 1.4 | Configure Bootloader" ansible.builtin.import_tasks: - file: cis_1.4.x.yml + file: cis_1.4.x.yml - name: "SECTION | 1.5 | Additional Process Hardening" ansible.builtin.import_tasks: - file: cis_1.5.x.yml + file: cis_1.5.x.yml -- name: "SECTION | 1.6 | Mandatory Access Control" - ansible.builtin.include_tasks: - file: cis_1.6.1.x.yml - when: not rhel9cis_selinux_disable +- name: "SECTION | 1.6 | Configure system wide crypto policy" + ansible.builtin.import_tasks: + file: cis_1.6.x.yml - name: "SECTION | 1.7 | Command Line Warning Banners" ansible.builtin.import_tasks: - file: cis_1.7.x.yml + file: cis_1.7.x.yml - name: "SECTION | 1.8 | Gnome Display Manager" ansible.builtin.import_tasks: - file: cis_1.8.x.yml - -- name: "SECTION | 1.9 | Updates and Patches" - ansible.builtin.import_tasks: - file: cis_1.9.yml - -- name: "SECTION | 1.10 | Crypto policies" - ansible.builtin.include_tasks: - file: cis_1.10.yml - when: - - not system_is_ec2 + file: cis_1.8.x.yml diff --git a/tasks/warning_facts.yml b/tasks/warning_facts.yml index 6e80487..98cd4b6 100644 --- a/tasks/warning_facts.yml +++ b/tasks/warning_facts.yml @@ -16,5 +16,5 @@ # the count increases by a value of 1 - name: "{{ warn_control_id }} | AUDIT | Set fact for manual task warning." ansible.builtin.set_fact: - warn_control_list: "{{ warn_control_list }} [{{ warn_control_id }}]" - warn_count: "{{ warn_count | int + 1 }}" + warn_control_list: "{{ warn_control_list }} [{{ warn_control_id }}]" + warn_count: "{{ warn_count | int + 1 }}" diff --git a/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 new file mode 100644 index 0000000..2a593d7 --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 @@ -0,0 +1,6 @@ +# This is a subpolicy dropping the SHA1 hash and signature support +# Carried out as part of CIS Benchmark + +hash = -SHA1 +sign = -*-SHA1 +sha1_in_certs = 0 diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 new file mode 100644 index 0000000..8eb8ae8 --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 @@ -0,0 +1,5 @@ +# This is a subpolicy to disable all CBC mode ciphers +# for the SSH protocol (libssh and OpenSSH) +# Carried out as part of CIS Benchmark + +cipher@SSH = -*-CBC diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 new file mode 100644 index 0000000..03fe414 --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 @@ -0,0 +1,5 @@ +# This is a subpolicy to disable the chacha20-poly1305 ciphers +# for the SSH protocol (libssh and OpenSSH) +# Carried out as part of CIS Benchmark + +cipher@SSH = -CHACHA20-POLY1305 diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 new file mode 100644 index 0000000..fe5fb7f --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 @@ -0,0 +1,5 @@ +# This is a subpolicy to disable Encrypt then MAC +# for the SSH protocol (libssh and OpenSSH) +# Carried out as part of CIS Benchmark + +etm@SSH = DISABLE_ETM diff --git a/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 new file mode 100644 index 0000000..ace7fa0 --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 @@ -0,0 +1,4 @@ +# This is a subpolicy to disable weak macs +# Carried out as part of CIS Benchmark + +mac = -*-64 diff --git a/templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 b/templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 index 11b3e2a..11a93f2 100644 --- a/templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 +++ b/templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 @@ -1,7 +1,12 @@ ## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! -{% if rhel9cis_rule_1_5_3 %} -# Kernel sysctl -# CIS 1.5.3 +{% if rhel9cis_rule_1_5_1 %} +# Adress space randomise +# CIS 1.5.1 kernel.randomize_va_space = 2 {% endif %} +{% if rhel9cis_rule_1_5_2 %} +# Ptrace scope +# CIS 1.5.2 +kernel.yama.ptrace_scope = 1 +{% endif %} diff --git a/templates/fs_with_cves.sh b/templates/fs_with_cves.sh new file mode 100644 index 0000000..89ba49b --- /dev/null +++ b/templates/fs_with_cves.sh @@ -0,0 +1,60 @@ +{% raw %} +#! /usr/bin/env bash + +# Based on original Script provided by CIS +# CVEs correct at time of creation - April2024 + +#! /usr/bin/env bash + +{ + a_output=(); a_output2=(); a_modprope_config=(); a_excluded=(); a_available_modules=() + a_ignore=("xfs" "vfat" "ext2" "ext3" "ext4") + a_cve_exists=("afs" "ceph" "cifs" "exfat" "ext" "fat" "fscache" "fuse" "gfs2" "nfs_common" "nfsd" "smbfs_common") + f_module_chk() + { + l_out2=""; grep -Pq -- "\b$l_mod_name\b" <<< "${a_cve_exists[*]}" && l_out2=" <- CVE exists!" + if ! grep -Pq -- '\bblacklist\h+'"$l_mod_name"'\b' <<< "${a_modprope_config[*]}"; then + a_output2+=(" - Kernel module: \"$l_mod_name\" is not fully disabled $l_out2") + elif ! grep -Pq -- '\binstall\h+'"$l_mod_name"'\h+\/bin\/(false|true)\b' <<< "${a_modprope_config[*]}"; then + a_output2+=(" - Kernel module: \"$l_mod_name\" is not fully disabled $l_out2") + fi + if lsmod | grep "$l_mod_name" &> /dev/null; then # Check if the module is currently loaded + l_output2+=(" - Kernel module: \"$l_mod_name\" is loaded" "") + fi + } + while IFS= read -r -d $'\0' l_module_dir; do + a_available_modules+=("$(basename "$l_module_dir")") + done < <(find "$(readlink -f /lib/modules/"$(uname -r)"/kernel/fs)" -mindepth 1 -maxdepth 1 -type d ! -empty -print0) + while IFS= read -r l_exclude; do + if grep -Pq -- "\b$l_exclude\b" <<< "${a_cve_exists[*]}"; then + a_output2+=(" - ** WARNING: kernel module: \"$l_exclude\" has a CVE and is currently mounted! **") + elif + grep -Pq -- "\b$l_exclude\b" <<< "${a_available_modules[*]}"; then + a_output+=(" - Kernel module: \"$l_exclude\" is currently mounted - do NOT unload or disable") + fi + ! grep -Pq -- "\b$l_exclude\b" <<< "${a_ignore[*]}" && a_ignore+=("$l_exclude") + done < <(findmnt -knD | awk '{print $2}' | sort -u) + while IFS= read -r l_config; do + a_modprope_config+=("$l_config") + done < <(modprobe --showconfig | grep -P '^\h*(blacklist|install)') + for l_mod_name in "${a_available_modules[@]}"; do # Iterate over all filesystem modules + [[ "$l_mod_name" =~ overlay ]] && l_mod_name="${l_mod_name::-2}" + if grep -Pq -- "\b$l_mod_name\b" <<< "${a_ignore[*]}"; then + a_excluded+=(" - Kernel module: \"$l_mod_name\"") + else + f_module_chk + fi + done +# Output findings + + echo "### Script can be found at ${BASH_SOURCE} ##" + if [ "${#a_output2[@]}" -le 0 ]; then + printf '%s\n' "" " - No unused filesystem kernel modules are enabled" "${a_output[@]}" "" + else + printf '%s\n' "" "-- Audit Result: --" " ** REVIEW the following **" "${a_output2[@]}" + # Changed return value to capture error + exit 99 + #[ "${#a_output[@]}" -gt 0 ] && printf '%s\n' "" "-- Correctly set: --" "${a_output[@]}" "" + fi +} +{% endraw %} diff --git a/vars/main.yml b/vars/main.yml index 6f73a63..68fe21d 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -11,6 +11,7 @@ rhel9cis_allowed_crypto_policies_modules: - 'OSPP' - 'AD-SUPPORT' - 'AD-SUPPORT-LEGACY' + - 'NO-SHA1' # Used to control warning summary warn_control_list: ""