diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e53f665..acdd896 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,16 +7,21 @@ ci: repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: # Safety - id: detect-aws-credentials + name: Detect AWS Credentials - id: detect-private-key + name: Detect Private Keys # git checks - id: check-merge-conflict + name: Check for merge conflicts - id: check-added-large-files + name: Check for Large files - id: check-case-conflict + name: Check case conflict # General checks - id: trailing-whitespace @@ -27,21 +32,21 @@ repos: types: [text] args: [--markdown-linebreak-ext=md] - id: end-of-file-fixer + name: Ensure line at end of file # Scan for passwords - repo: https://github.com/Yelp/detect-secrets rev: v1.5.0 hooks: - id: detect-secrets - exclude: templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 - repo: https://github.com/gitleaks/gitleaks - rev: v8.18.4 + rev: v8.21.2 hooks: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v24.7.0 + rev: v24.10.0 hooks: - id: ansible-lint name: Ansible-lint @@ -52,14 +57,15 @@ repos: # https://github.com/ansible/ansible-lint/issues/611 pass_filenames: false always_run: true - additional_dependencies: + # additional_dependencies: # https://github.com/pre-commit/pre-commit/issues/1526 # If you want to use specific version of ansible-core or ansible, feel # free to override `additional_dependencies` in your own hook config # file. - - ansible-core>=2.10.1 + # - ansible-core>=2.10.1 - repo: https://github.com/adrienverge/yamllint.git rev: v1.35.1 # or higher tag hooks: - id: yamllint + name: Check YAML Lint diff --git a/.yamllint b/.yamllint index 4cf7047..fa7b697 100644 --- a/.yamllint +++ b/.yamllint @@ -1,6 +1,5 @@ --- extends: default -locale: en_US.UTF-8 ignore: | tests/ molecule/ diff --git a/defaults/main.yml b/defaults/main.yml index e210596..816eb11 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -495,6 +495,11 @@ rhel9cis_rule_7_2_9: true ## Section 1 vars +## Ability to enabe debug on mounts to assist in troubleshooting +# Mount point changes are set based upon facts created in Prelim +# these then build the variable and options that is passed to the handler to set the mount point for the controls in section1. +rhel9cis_debug_mount_data: false + ## Control 1.1.2 # If set to `true`, rule will be implemented using the `tmp.mount` systemd-service, # otherwise fstab configuration will be used. @@ -1034,8 +1039,7 @@ min_int_uid: 1000 max_int_uid: 65533 ## Section6 vars - -## Control 6.1.1 - allow aide to be configured +## Control 6.1.x - allow aide to be configured # AIDE is a file integrity checking tool, similar in nature to Tripwire. # While it cannot prevent intrusions, it can detect unauthorized changes # to configuration files by alerting when the files are changed. Review @@ -1043,6 +1047,16 @@ max_int_uid: 65533 # By setting this variable to `true`, all of the settings related to AIDE will be applied! rhel9cis_config_aide: true +# If DB file older than below will automatically rebuild DB +# e.g. options:1w = 1 week, 1d = 1day 1h = 1 hour +rhel9cis_aide_db_file_age: 1w + +# If aide already setup this forces a new DB to be created +rhel9cis_aide_db_recreate: false + +# allows to change db file, not config need to be adjusted too +rhel9cis_aide_db_file: /var/lib/aide/aide.db + ## Control 6.1.2 AIDE cron settings ## How the aide schedule is run either cron or timer diff --git a/templates/fs_with_cves.sh b/files/fs_with_cves.sh similarity index 98% rename from templates/fs_with_cves.sh rename to files/fs_with_cves.sh index a6d937c..a2bc1b7 100644 --- a/templates/fs_with_cves.sh +++ b/files/fs_with_cves.sh @@ -1,4 +1,4 @@ -{% raw %}#! /usr/bin/env bash +#! /usr/bin/env bash # Based on original Script provided by CIS # CVEs correct at time of creation - April2024 @@ -54,4 +54,3 @@ #[ "${#a_output[@]}" -gt 0 ] && printf '%s\n' "" "-- Correctly set: --" "${a_output[@]}" "" fi } -{% endraw %} diff --git a/handlers/main.yml b/handlers/main.yml index f6a2806..3c51ddf 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,6 +1,149 @@ --- # handlers file for RHEL9-CIS +- name: "Adding options for /tmp" + when: not rhel9cis_tmp_svc + vars: + mount_point: '/tmp' + ansible.posix.mount: + path: "{{ mount_point }}" + src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}" + state: present + fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + listen: "Remount /tmp" + +- name: "Remounting /tmp" + vars: + mount_point: '/tmp' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + listen: "Remount /tmp" + +- name: "Remounting /tmp systemd" + vars: + mount_point: '/tmp' + ansible.builtin.systemd: + name: tmp.mount + state: restarted + daemon_reload: true + listen: "Remount /tmp" + +- name: "Adding options for /dev/shm" + vars: + mount_point: '/dev/shm' + ansible.posix.mount: + path: "{{ mount_point }}" + src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}" + state: present + fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + listen: "Remount /dev/shm" + +- name: "Remounting /dev/shm" + vars: + mount_point: '/dev/shm' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + listen: "Remount /dev/shm" + +- name: "Adding options for /home" + vars: + mount_point: '/home' + ansible.posix.mount: + path: "{{ mount_point }}" + src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}" + state: present + fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + listen: "Remount /home" + +- name: "Remounting /home" + vars: + mount_point: '/home' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + listen: "Remount /home" + +- name: "Adding options for /var" + vars: + mount_point: '/var' + ansible.posix.mount: + path: "{{ mount_point }}" + src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}" + state: present + fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + listen: "Remount /var" + +- name: "Remounting /var" + vars: + mount_point: '/var' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + listen: "Remount /var" + +- name: "Adding options for /var/tmp" + vars: + mount_point: '/var/tmp' + ansible.posix.mount: + path: "{{ mount_point }}" + src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}" + state: present + fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + listen: "Remount /var/tmp" + +- name: "Remounting /var/tmp" + vars: + mount_point: '/var/tmp' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + listen: "Remount /var/tmp" + +- name: "Adding options for /var/log" + vars: + mount_point: '/var/log' + ansible.posix.mount: + path: "{{ mount_point }}" + src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}" + state: present + fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + listen: "Remount /var/log" + +- name: "Remounting /var/log" + vars: + mount_point: '/var/log' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + listen: "Remount /var/log" + +- name: "Adding options for /var/log/audit" + vars: + mount_point: '/var/log/audit' + ansible.posix.mount: + path: "{{ mount_point }}" + src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}" + state: present + fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + listen: "Remount /var/log/audit" + +- name: "Remounting /var/log/audit" + vars: + mount_point: '/var/log/audit' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + listen: "Remount /var/log/audit" + - name: Reload sysctl ansible.builtin.command: sysctl --system changed_when: true @@ -32,11 +175,6 @@ masked: false state: reloaded -- name: Remount tmp - ansible.posix.mount: - 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 %}" @@ -71,8 +209,8 @@ - name: Grub2cfg ansible.builtin.command: "grub2-mkconfig -o /boot/grub2/grub.cfg" - ignore_errors: true # noqa ignore-errors changed_when: true + ignore_errors: true # noqa ignore-errors - name: Restart rsyslog ansible.builtin.systemd: @@ -110,9 +248,16 @@ msg: "Reboot required for auditd to apply new rules as immutable set" notify: Change_requires_reboot -- name: Restart auditd # noqa command-instead-of-module - ansible.builtin.command: service auditd restart +- name: Stop auditd process + ansible.builtin.command: systemctl kill auditd changed_when: true + listen: Restart auditd + +- name: Start auditd process + ansible.builtin.systemd_service: + name: auditd + state: started + listen: Restart auditd - name: Change_requires_reboot ansible.builtin.set_fact: diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index 7c2243f..c1fd66e 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -7,7 +7,7 @@ audit_pkg_arch_name: AMD64 - name: Pre Audit Setup | Set audit package name | ARM64 - when: ansible_facts.machine == "aarch64" + when: ansible_facts.machine == "arm64" ansible.builtin.set_fact: audit_pkg_arch_name: ARM64 @@ -19,13 +19,13 @@ owner: root group: root checksum: "{{ audit_bin_version[audit_pkg_arch_name + '_checksum'] }}" - mode: "0555" + mode: 'u+x,go-w' - name: Pre Audit Setup | Copy audit binary when: get_audit_binary_method == 'copy' ansible.builtin.copy: src: "{{ audit_bin_copy_location }}" dest: "{{ audit_bin }}" - mode: "0555" owner: root group: root + mode: 'u+x,go-w' diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index c3d9596..1377f9f 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -2,7 +2,7 @@ - name: Audit_Only | Create local Directories for hosts when: fetch_audit_files ansible.builtin.file: - mode: "0755" + mode: 'u+x,go-w' path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}" recurse: true state: directory @@ -14,7 +14,7 @@ ansible.builtin.fetch: dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/" flat: true - mode: "0644" + mode: 'go-wx' src: "{{ pre_audit_outfile }}" - name: Audit_only | Show Audit Summary diff --git a/tasks/auditd.yml b/tasks/auditd.yml index 502497c..7022e2c 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -26,7 +26,7 @@ ansible.builtin.import_tasks: file: warning_facts.yml vars: - warn_control_id: 'Auditd template updated, see diff output for details' + warn_control_id: 'Auditd template updated, validate as expected' - name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added | stat file ansible.builtin.stat: diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 102acef..86c1cac 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -12,6 +12,7 @@ - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries" ansible.builtin.set_fact: rhel9cis_passwd: "{{ prelim_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" + loop: "{{ prelim_passwd_file_audit.stdout_lines }}" vars: ld_passwd_regex: >- ^(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*) diff --git a/tasks/post.yml b/tasks/post.yml index b6efdfe..383cdf6 100644 --- a/tasks/post.yml +++ b/tasks/post.yml @@ -28,7 +28,8 @@ - name: POST | reboot system if changes require it and not skipped when: change_requires_reboot - tags: always + tags: + - always vars: warn_control_id: Reboot_required block: diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 294d45a..54d5785 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -8,7 +8,7 @@ AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" AUDIT_FILE: goss.yml -- name: Post Audit | Ensure audit files readable by users +- name: Post Audit | ensure audit files readable by users ansible.builtin.file: path: "{{ item }}" mode: '0644' @@ -22,8 +22,8 @@ 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 + register: post_audit_summary - name: Post Audit | Set Fact for audit summary ansible.builtin.set_fact: @@ -33,9 +33,9 @@ when: audit_format == "documentation" block: - name: Post Audit | Capture audit data if documentation format - ansible.builtin.shell: tail -2 "{{ post_audit_outfile }}" | tac | tr '\n' ' ' - register: post_audit_summary + ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' changed_when: false + register: post_audit_summary - name: Post Audit | Set Fact for audit summary ansible.builtin.set_fact: diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index c6a531a..61959fa 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -5,11 +5,11 @@ ansible.builtin.include_tasks: file: LE_audit_setup.yml -- name: Pre Audit Setup | Ensure {{ audit_conf_dir }} exists # noqa name[template] +- name: Pre Audit Setup | Ensure existence of {{ audit_conf_dir }} # noqa name[template] ansible.builtin.file: path: "{{ audit_conf_dir }}" + mode: 'go-w' state: directory - mode: "0755" - name: Pre Audit Setup | If using git for content set up when: audit_content == 'git' @@ -52,10 +52,10 @@ - name: Pre Audit Setup | Check for goss file ansible.builtin.stat: path: "{{ audit_bin }}" - register: discovered_goss_available + register: prelim_goss_available - name: Pre Audit Setup | If audit ensure goss is available - when: not discovered_goss_available.stat.exists + when: not prelim_goss_available.stat.exists ansible.builtin.assert: msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}" @@ -67,10 +67,10 @@ ansible.builtin.template: src: ansible_vars_goss.yml.j2 dest: "{{ audit_vars_path }}" - mode: "0600" + mode: 'go-rwx' -- name: Pre Audit | Run pre_remediation {{ benchmark }} audit # noqa name[template] - ansible.builtin.command: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" +- name: Pre Audit | Run pre_remediation audit {{ benchmark }} # noqa name[template] + ansible.builtin.command: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" @@ -93,7 +93,7 @@ when: audit_format == "documentation" block: - name: Pre Audit | Capture audit data if documentation format - ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' + ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' changed_when: false register: pre_audit_summary diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 1e67bb3..6602d28 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -52,10 +52,34 @@ name: python3-libselinux state: present -- name: "PRELIM | AUDIT | Section 1.1 | Create list of mount points" +- name: PRELIM | AUDIT | Section 1.1 | Create list of mount points tags: always ansible.builtin.set_fact: - mount_names: "{{ ansible_facts.mounts | map(attribute='mount') | list }}" + prelim_mount_names: "{{ ansible_facts.mounts | map(attribute='mount') | list }}" + +- name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options + tags: always + block: + - name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options - call mount # noqa command-instead-of-module + ansible.builtin.shell: | + mount | awk '{print $1, $3, $5, $6}' + changed_when: false + register: prelim_mount_output + + - name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options - build fact # This is inherited and used in mountpoints tasks + ansible.builtin.set_fact: + prelim_mount_point_fs_and_options: >- + {%- set prelim_mount_point_fs_and_options = {} -%} + {%- for line in prelim_mount_output.stdout_lines -%} + {%- set fields = line.split() -%} + {%- set _ = prelim_mount_point_fs_and_options.update({fields[1]: {'src': fields[0], 'fs_type': fields[2], 'original_options': fields[3][1:-1].split(','), 'options': fields[3][1:-1].split(',')}}) -%} + {%- endfor -%} + {{ prelim_mount_point_fs_and_options }} + + - name: "PRELIM | AUDIT | Debug of mount variables to assist in troubleshooting" + when: rhel9cis_debug_mount_data + ansible.builtin.debug: + msg: "{{ prelim_mount_point_fs_and_options }}" - name: "PRELIM | PATCH | Update to latest gpg keys" when: @@ -80,7 +104,7 @@ - name: "PRELIM | AUDIT | Import gpg keys | Check Package" # noqa command-instead-of-module when: "'not installed' in prelim_check_gpg_imported.stdout" - ansible.builtin.shell: rpm -qi redhat-release | grep Signature + ansible.builtin.shell: rpm -qi redhat-release | grep Signature # noqa command-instead-of-module changed_when: false failed_when: false register: prelim_os_gpg_package_valid @@ -89,8 +113,9 @@ when: - "'not installed' in prelim_check_gpg_imported.stdout" - "'Key ID 199e2f91fd431d51' in prelim_os_gpg_package_valid.stdout" - ansible.builtin.command: rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release - changed_when: false + ansible.builtin.rpm_key: + key: /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release + state: present - name: "PRELIM | AUDIT | Check systemd coredump" when: rhel9cis_rule_1_5_4 @@ -239,7 +264,7 @@ ansible.builtin.file: path: /etc/systemd/journald.conf.d state: directory - mode: 'go-w' + mode: 'u+x,g-w,o-rwx' - name: "PRELIM | PATCH | Configure System Accounting (auditd)" when: diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index 579fb1b..adc094d 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -268,7 +268,7 @@ 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: + ansible.builtin.copy: src: fs_with_cves.sh dest: /var/fs_with_cves.sh owner: root @@ -284,9 +284,7 @@ - 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 }}" + 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 diff --git a/tasks/section_1/cis_1.1.2.1.x.yml b/tasks/section_1/cis_1.1.2.1.x.yml index 4457624..9cca1ec 100644 --- a/tasks/section_1/cis_1.1.2.1.x.yml +++ b/tasks/section_1/cis_1.1.2.1.x.yml @@ -2,7 +2,7 @@ - name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition" when: - - required_mount not in mount_names + - required_mount not in prelim_mount_names - rhel9cis_rule_1_1_2_1_1 tags: - level1-server @@ -12,62 +12,104 @@ - rule_1.1.2.1.1 - NIST800-53R5_CM-7 vars: - warn_control_id: '1.1.2.1.1' - required_mount: '/tmp' + 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. Please investigate this manual task" + - name: "1.1.2.1.1 | AUDIT | Ensure /tmp is a separate partition | check for mount" + ansible.builtin.command: findmnt -kn "{{ required_mount }}" + changed_when: false + failed_when: discovered_tmp_mount.rc not in [ 0, 1 ] + register: discovered_tmp_mount - - name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition | Present" + - name: "1.1.2.1.1 | AUDIT | Ensure /tmp is a separate partition | Absent" + when: discovered_tmp_mount is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.1.1 | AUDIT | Ensure /tmp is a separate partition | Present" + when: discovered_tmp_mount is undefined 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: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_1_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_1_3) %},nosuid{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_2_1_4) %},noexec{% endif %}" - notify: Remount tmp - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" +- name: "1.1.2.1.2 | PATCH | Ensure nodev option set on /tmp partition" when: - - item.mount == "/tmp" + - prelim_mount_point_fs_and_options[mount_point] is defined + - not prelim_mount_point_fs_and_options[mount_point]['src'] == "tmpfs" + - rhel9cis_rule_1_1_2_1_2 - 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 - - NIST800-53R5_CM-7 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 + vars: + mount_point: "/tmp" + required_option: nodev + notify: &mount_option_notify + - "Remount {{ mount_point }}" + ansible.builtin.set_fact: &mount_option_set_fact + prelim_mount_point_fs_and_options: | + {{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + changed_when: &mount_option_changed_when + - required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options'] + +- name: "1.1.2.1.3 | PATCH | Ensure nosuid option set on /tmp partition" + when: + - prelim_mount_point_fs_and_options[mount_point] is defined + - not prelim_mount_point_fs_and_options[mount_point]['src'] == "tmpfs" + - rhel9cis_rule_1_1_2_1_3 + - not rhel9cis_tmp_svc + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1.1.2.1.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/tmp" + required_option: nosuid + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when + +- name: "1.1.2.1.4 | PATCH | Ensure noexec option set on /tmp partition" + when: + - prelim_mount_point_fs_and_options[mount_point] is defined + - not prelim_mount_point_fs_and_options[mount_point]['src'] == "tmpfs" + - rhel9cis_rule_1_1_2_1_4 + - not rhel9cis_tmp_svc + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1.1.2.1.4 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/tmp" + required_option: noexec + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when # 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" + "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 + - 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 @@ -79,10 +121,12 @@ - rule_1.1.2.1.4 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 + vars: + mount_point: "/tmp" ansible.builtin.template: src: etc/systemd/system/tmp.mount.j2 dest: /etc/systemd/system/tmp.mount owner: root group: root mode: 'go-wx' - notify: Systemd restart tmp.mount + notify: *mount_option_notify diff --git a/tasks/section_1/cis_1.1.2.2.x.yml b/tasks/section_1/cis_1.1.2.2.x.yml index 6f0df56..57e92eb 100644 --- a/tasks/section_1/cis_1.1.2.2.x.yml +++ b/tasks/section_1/cis_1.1.2.2.x.yml @@ -1,8 +1,9 @@ --- -# 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 +- name: "1.1.2.2.1 | PATCH | Ensure /dev/shm is a separate partition" + when: + - rhel9cis_rule_1_1_2_2_1 + - required_mount not in prelim_mount_names tags: - level1-server - level1-workstation @@ -11,46 +12,84 @@ - rule_1.1.2.2.1 - NIST800-53R5_CM-7 vars: - warn_control_id: '1.1.2.2.1' + warn_control_id: "1.1.2.2.1" + required_mount: "/dev/shm" block: - - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | check exists" # noqa command-instead-of-module - ansible.builtin.shell: mount -l | grep -w /dev/shm + - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | check for mount" + ansible.builtin.command: findmnt -kn "{{ required_mount }}" changed_when: false - register: discovered_dev_shm_mount_check + failed_when: discovered_dev_shm_mount.rc not in [ 0, 1 ] + register: discovered_dev_shm_mount - - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition" - when: discovered_dev_shm_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. Please investigate this manual task" + - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | Absent" + when: discovered_dev_shm_mount is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" - - 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.1 | AUDIT | Ensure /dev/shm is a separate partition | Present" + when: discovered_dev_shm_mount is undefined + ansible.builtin.import_tasks: + file: warning_facts.yml -- name: | - "1.1.2.2.2 | PATCH | Ensure nodev option set on /dev/shm partition - 1.1.2.2.3 | PATCH | Ensure nosuid option set on /dev/shm partition - 1.1.2.2.4 | PATCH | Ensure noexec option set on /dev/shm partition" +- name: "1.1.2.2.2 | PATCH | Ensure nodev 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 + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_2_2 tags: - level1-server - level1-workstation - patch - mounts - rule_1.1.2.2.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/dev/shm" + required_option: nodev + notify: &mount_option_notify + - "Remount {{ mount_point }}" + ansible.builtin.set_fact: &mount_option_set_fact + prelim_mount_point_fs_and_options: | + {{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + changed_when: &mount_option_changed_when + - required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options'] + +- name: "1.1.2.2.3 | PATCH | Ensure nosuid option set on /dev/shm partition" + when: + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_2_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.2.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/dev/shm" + required_option: nosuid + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when + +- name: "1.1.2.2.4 | PATCH | Ensure noexec option set on /dev/shm partition" + when: + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_2_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.2.4 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - 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 + vars: + mount_point: "/dev/shm" + required_option: noexec + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml index 8894013..998d1ba 100644 --- a/tasks/section_1/cis_1.1.2.3.x.yml +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -1,52 +1,74 @@ --- - -- name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home" +- name: "1.1.2.3.1 | PATCH | Ensure /home is a separate partition" when: - - required_mount not in mount_names - rhel9cis_rule_1_1_2_3_1 + - required_mount not in prelim_mount_names tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - audit - mounts - - rule_1_1_2.3.1 + - rule_1.1.2.3.1 - NIST800-53R5_CM-7 vars: - warn_control_id: '1.1.2.3.1' - required_mount: '/home' + 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. Please investigate this manual task" + - name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | check for mount" + ansible.builtin.command: findmnt -kn "{{ required_mount }}" + changed_when: false + failed_when: discovered_home_mount.rc not in [ 0, 1 ] + register: discovered_home_mount - - name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home | Present" + - name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | Absent" + when: discovered_dev_shm_mount is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | Present" + when: discovered_dev_shm_mount is undefined 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" +- name: "1.1.2.3.2 | PATCH | Ensure nodev option set on /home partition" when: - - item.mount == "/home" - - rhel9cis_rule_1_1_2_3_2 or - rhel9cis_rule_1_1_2_3_3 + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_3_2 tags: - level1-server - level1-workstation - patch - mounts - rule_1.1.2.3.2 - - rule_1.1.2.3.3 - - NIST800-53R5_CM-7 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.posix.mount: - name: /home - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_3_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_3_3) %},nosuid{% endif %}" - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot + vars: + mount_point: "/home" + required_option: nodev + notify: &mount_option_notify + - "Remount {{ mount_point }}" + ansible.builtin.set_fact: &mount_option_set_fact + prelim_mount_point_fs_and_options: | + {{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + changed_when: &mount_option_changed_when + - required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options'] + +- name: "1.1.2.3.3 | PATCH | Ensure nosuid option set on /home partition" + when: + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_3_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1.1.2.3.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/home" + required_option: nosuid + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml index 328ec8b..e0afd4e 100644 --- a/tasks/section_1/cis_1.1.2.4.x.yml +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -1,52 +1,75 @@ --- -- name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var" +- name: "1.1.2.4.1 | PATCH | Ensure /var is a separate partition" when: - - required_mount not in mount_names - rhel9cis_rule_1_1_2_4_1 + - required_mount not in prelim_mount_names tags: - - level2-server - - level2-workstation - - patch + - level1-server + - level1-workstation + - audit - mounts - - rule_1_1_2.4.1 + - rule_1.1.2.4.1 - NIST800-53R5_CM-7 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. Please investigate this manual task" + - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | check for mount" + ansible.builtin.command: findmnt -kn "{{ required_mount }}" + changed_when: false + failed_when: discovered_var_mount.rc not in [ 0, 1 ] + register: discovered_var_mount - - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Present" + - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Absent" + when: discovered_dev_shm_mount is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Present" + when: discovered_dev_shm_mount is undefined 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" +- name: "1.1.2.4.2 | PATCH | Ensure nodev option set on /var partition" when: - - item.mount == "/var" - - rhel9cis_rule_1_1_2_4_2 or - rhel9cis_rule_1_1_2_4_3 + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_4_2 tags: - level1-server - level1-workstation - patch - mounts - rule_1.1.2.4.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/var" + required_option: nodev + notify: &mount_option_notify + - "Remount {{ mount_point }}" + ansible.builtin.set_fact: &mount_option_set_fact + prelim_mount_point_fs_and_options: | + {{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + changed_when: &mount_option_changed_when + - required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options'] + +- name: "1.1.2.4.3 | PATCH | Ensure nosuid option set on /var partition" + when: + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_4_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.4.3 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.posix.mount: - name: /var - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_4_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_4_2) %},nosuid{% endif %}" - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot + vars: + mount_point: "/var" + required_option: nosuid + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when diff --git a/tasks/section_1/cis_1.1.2.5.x.yml b/tasks/section_1/cis_1.1.2.5.x.yml index dbb7b97..180d016 100644 --- a/tasks/section_1/cis_1.1.2.5.x.yml +++ b/tasks/section_1/cis_1.1.2.5.x.yml @@ -1,56 +1,95 @@ --- -# Skips if mount is absent -- name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp" +- name: "1.1.2.5.1 | PATCH | Ensure /var/tmp is a separate partition" when: - - required_mount not in mount_names - rhel9cis_rule_1_1_2_5_1 + - required_mount not in prelim_mount_names tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - audit - mounts - - rule_1_1_2.5.1 + - rule_1.1.2.5.1 - NIST800-53R5_CM-7 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. Please investigate this manual task" + - name: "1.1.2.5.1 | AUDIT | Ensure /var/tmp is a separate partition | check for mount" + ansible.builtin.command: findmnt -kn "{{ required_mount }}" + changed_when: false + failed_when: discovered_var_tmp_mount.rc not in [ 0, 1 ] + register: discovered_var_tmp_mount - - name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp | Present" + - name: "1.1.2.5.1 | AUDIT | Ensure /var/tmp is a separate partition | Absent" + when: discovered_var_tmp_mount is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.5.1 | AUDIT | Ensure /var/tmp is a separate partition | Present" + when: discovered_var_tmp_mount is undefined 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" +- name: "1.1.2.5.2 | PATCH | Ensure nodev 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 + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_5_2 tags: - level1-server - level1-workstation - patch - mounts - rule_1.1.2.5.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/var/tmp" + required_option: nodev + notify: &mount_option_notify + - "Remount {{ mount_point }}" + ansible.builtin.set_fact: &mount_option_set_fact + prelim_mount_point_fs_and_options: | + {{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + changed_when: &mount_option_changed_when + - required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options'] + +- name: "1.1.2.5.3 | PATCH | Ensure nosuid option set on /var/tmp partition" + when: + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_5_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.5.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/var/tmp" + required_option: nosuid + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when + +- name: "1.1.2.5.4 | PATCH | Ensure noexec option set on /var/tmp partition" + when: + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_5_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.5.4 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.posix.mount: - name: /var/tmp - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_5_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_5_3) %},nosuid{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_2_5_4) %},noexec{% endif %}" - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot + vars: + mount_point: "/var/tmp" + required_option: noexec + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when diff --git a/tasks/section_1/cis_1.1.2.6.x.yml b/tasks/section_1/cis_1.1.2.6.x.yml index c38240c..765de3d 100644 --- a/tasks/section_1/cis_1.1.2.6.x.yml +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -1,54 +1,95 @@ --- -- name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log" +- name: "1/.1 | PATCH | Ensure /var/log is a separate partition" when: - - required_mount not in mount_names - rhel9cis_rule_1_1_2_6_1 + - required_mount not in prelim_mount_names tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - audit - mounts - - rule_1_1_2.6.1 + - rule_1.1.2.6.1 - NIST800-53R5_CM-7 vars: warn_control_id: '1.1.2.6.1' required_mount: '/var/log' block: - - name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. Please investigate this manual task" + - name: "1.1.2.6.1 | AUDIT | Ensure /var/log is a separate partition | check for mount" + ansible.builtin.command: findmnt -kn "{{ required_mount }}" + changed_when: false + failed_when: discovered_var_log_mount.rc not in [ 0, 1 ] + register: discovered_var_log_mount - - name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log | Present" + - name: "1.1.2.6.1 | AUDIT | Ensure /var/log is a separate partition | Absent" + when: discovered_var_log_mount is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.6.1 | AUDIT | Ensure /var/log is a separate partition | Present" + when: discovered_var_log_mount is undefined 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" +- name: "1.1.2.6.2 | PATCH | Ensure nodev 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 + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_6_2 tags: - level1-server - level1-workstation - patch - mounts - rule_1.1.2.6.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/var/log" + required_option: nodev + notify: &mount_option_notify + - "Remount {{ mount_point }}" + ansible.builtin.set_fact: &mount_option_set_fact + prelim_mount_point_fs_and_options: | + {{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + changed_when: &mount_option_changed_when + - required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options'] + +- name: "1.1.2.6.3 | PATCH | Ensure nosuid option set on /var/log partition" + when: + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_6_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.6.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/var/log" + required_option: nosuid + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when + +- name: "1.1.2.6.4 | PATCH | Ensure noexec option set on /var/log partition" + when: + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_6_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.6.4 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.posix.mount: - name: /var/log - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_6_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_6_3) %},nosuid{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_2_6_4) %},noexec{% endif %}" - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot + vars: + mount_point: "/var/log" + required_option: noexec + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when diff --git a/tasks/section_1/cis_1.1.2.7.x.yml b/tasks/section_1/cis_1.1.2.7.x.yml index 526e46b..2dc5939 100644 --- a/tasks/section_1/cis_1.1.2.7.x.yml +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -1,54 +1,95 @@ --- -- name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit" +- name: "1/.1 | PATCH | Ensure /var/log/audit is a separate partition" when: - - required_mount not in mount_names - rhel9cis_rule_1_1_2_7_1 + - required_mount not in prelim_mount_names tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - audit - mounts - - rule_1_1_2.7.1 + - rule_1.1.2.7.1 - NIST800-53R5_CM-7 vars: warn_control_id: '1.1.2.7.1' required_mount: '/var/log/audit' block: - - name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. Please investigate this manual task" + - name: "1.1.2.7.1 | AUDIT | Ensure /var/log/audit is a separate partition | check for mount" + ansible.builtin.command: findmnt -kn "{{ required_mount }}" + changed_when: false + failed_when: discovered_var_log_audit_mount.rc not in [ 0, 1 ] + register: discovered_var_log_audit_mount - - name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Present" + - name: "1.1.2.7.1 | AUDIT | Ensure /var/log/audit is a separate partition | Absent" + when: discovered_var_log_audit_mount is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.7.1 | AUDIT | Ensure /var/log/audit is a separate partition | Present" + when: discovered_var_log_audit_mount is undefined 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" +- name: "1.1.2.7.2 | PATCH | Ensure nodev option set on /var/log/audit partition" 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 + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_7_2 tags: - level1-server - level1-workstation - patch - mounts - rule_1.1.2.7.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/var/log/audit" + required_option: nodev + notify: &mount_option_notify + - "Remount {{ mount_point }}" + ansible.builtin.set_fact: &mount_option_set_fact + prelim_mount_point_fs_and_options: | + {{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + changed_when: &mount_option_changed_when + - required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options'] + +- name: "1.1.2.7.3 | PATCH | Ensure nosuid option set on /var/log/audit partition" + when: + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_7_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.7.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/var/log/audit" + required_option: nosuid + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when + +- name: "1.1.2.7.4 | PATCH | Ensure noexec option set on /var/log/audit partition" + when: + - prelim_mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_7_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.7.4 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.posix.mount: - name: /var/log/audit - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_7_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_7_3) %},nosuid{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_2_7_4) %},noexec{% endif %}" - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot + vars: + mount_point: "/var/log/audit" + required_option: noexec + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when diff --git a/tasks/section_1/cis_1.2.1.x.yml b/tasks/section_1/cis_1.2.1.x.yml index 28cd7cd..a5a8d71 100644 --- a/tasks/section_1/cis_1.2.1.x.yml +++ b/tasks/section_1/cis_1.2.1.x.yml @@ -14,20 +14,20 @@ - rule_1.2.1.1 - NIST800-53R5_SI-2 block: - - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | list installed pubkey keys" # noqa command-instead-of-module - ansible.builtin.shell: "rpm -qa | grep {{ os_gpg_key_pubkey_name }}" + - 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 }}" # noqa command-instead-of-module changed_when: false failed_when: false register: discovered_os_installed_pub_keys - - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | Query found keys" # noqa command-instead-of-module - when: discovered_os_installed_pub_keys.rc == 0 - ansible.builtin.shell: 'rpm -q --queryformat "%{PACKAGER} %{VERSION}\\n" {{ os_gpg_key_pubkey_name }} | grep "{{ os_gpg_key_pubkey_content }}"' + - 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: discovered_os_gpg_key_check - - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | expected keys fail" + - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | If expected keys fail" when: - discovered_os_installed_pub_keys.rc == 1 or discovered_os_gpg_key_check.rc == 1 diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index eaa0c60..e49e733 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -676,8 +676,8 @@ vars: warn_control_id: '2.1.22' block: - - name: "2.1.22 | AUDIT | Ensure only approved services are listening on a network interface | Get list of services" # noqa command-instead-of-module - ansible.builtin.command: systemctl list-units --type=service + - name: "2.1.22 | AUDIT | Ensure only approved services are listening on a network interface | Get list of services" + ansible.builtin.command: systemctl list-units --type=service # noqa command-instead-of-module changed_when: false failed_when: discovered_running_services.rc not in [ 0, 1 ] check_mode: false diff --git a/tasks/section_3/cis_3.2.x.yml b/tasks/section_3/cis_3.2.x.yml index 4903070..a49d907 100644 --- a/tasks/section_3/cis_3.2.x.yml +++ b/tasks/section_3/cis_3.2.x.yml @@ -17,7 +17,7 @@ regexp: '^(#)?install dccp(\\s|$)' line: "{{ item }}" create: true - mode: 'go-wx' + mode: 'u-x,go-rwx' loop: - install dccp /bin/true - blacklist dccp @@ -28,7 +28,7 @@ regexp: "^(#)?blacklist cramfs(\\s|$)" line: "blacklist cramfs" create: true - mode: 'go-wx' + mode: 'u-x,go-rwx' - name: "3.2.2 | PATCH | Ensure tipc kernel module is not available" when: rhel9cis_rule_3_2_2 @@ -47,7 +47,7 @@ regexp: '^(#)?install tipc(\\s|$)' line: "{{ item }}" create: true - mode: 'go-wx' + mode: 'u-x,go-rwx' loop: - install tipc /bin/true - blacklist tipc @@ -58,7 +58,7 @@ regexp: "^(#)?blacklist tipc(\\s|$)" line: "blacklist tipc" create: true - mode: 'go-wx' + mode: 'u-x,go-rwx' - name: "3.2.3 | PATCH | Ensure rds kernel module is not available" when: rhel9cis_rule_3_2_3 @@ -77,7 +77,7 @@ regexp: '^(#)?install rds(\\s|$)' line: "{{ item }}" create: true - mode: 'go-wx' + mode: 'u-x,go-rwx' loop: - install rds /bin/true - blacklist rds @@ -88,7 +88,7 @@ regexp: "^(#)?blacklist rds(\\s|$)" line: "blacklist rds" create: true - mode: 'go-wx' + mode: 'u-x,go-rwx' - name: "3.2.4 | PATCH | Ensure sctp kernel module is not available" when: rhel9cis_rule_3_2_4 @@ -107,7 +107,7 @@ regexp: '^(#)?install sctp(\\s|$)' line: "{{ item }}" create: true - mode: 'go-wx' + mode: 'u-x,go-rwx' loop: - install sctp /bin/true - blacklist sctp @@ -118,4 +118,4 @@ regexp: "^(#)?blacklist sctp(\\s|$)" line: "blacklist sctp" create: true - mode: 'go-wx' + mode: 'u-x,go-rwx' diff --git a/tasks/section_4/cis_4.3.x.yml b/tasks/section_4/cis_4.3.x.yml index 450ef3b..4e23998 100644 --- a/tasks/section_4/cis_4.3.x.yml +++ b/tasks/section_4/cis_4.3.x.yml @@ -22,19 +22,22 @@ - NIST800-55_CA-9 block: - name: "4.3.1 | AUDIT | Ensure nftables base chains exist | Get current chains for INPUT" - ansible.builtin.shell: nft list ruleset | grep 'hook input' + ansible.builtin.shell: | + nft list ruleset | grep 'hook input' changed_when: false failed_when: false register: discovered_nftables_input_chains - name: "4.3.1 | AUDIT | Ensure nftables base chains exist | Get current chains for FORWARD" - ansible.builtin.shell: nft list ruleset | grep 'hook forward' + ansible.builtin.shell: | + nft list ruleset | grep 'hook forward' changed_when: false failed_when: false register: discovered_nftables_forward_chains - name: "4.3.1 | AUDIT | Ensure nftables base chains exist | Get current chains for OUTPUT" - ansible.builtin.shell: nft list ruleset | grep 'hook output' + ansible.builtin.shell: | + nft list ruleset | grep 'hook output' changed_when: false failed_when: false register: discovered_nftables_output_chains @@ -71,13 +74,14 @@ - NIST800-55_CA-9 block: - name: "4.3.2 | AUDIT | Ensure nftables established connections are configured | Gather incoming connection rules" - ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state' + ansible.builtin.shell: | + nft list ruleset | awk '/hook input/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state' changed_when: false failed_when: false register: discovered_nftables_inconnectionrule - name: "4.3.2 | AUDIT | Ensure nftables established connections are configured | Gather outbound connection rules" - ansible.builtin.shell: nft list ruleset | awk '/hook output/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state' + ansible.builtin.command: nft list ruleset | awk '/hook output/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state' changed_when: false failed_when: false register: discovered_nftables_outconnectionrule @@ -123,25 +127,29 @@ - NIST800-55_CA-9 block: - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for hook input deny policy" - ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook input' + ansible.builtin.shell: | + nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook input' failed_when: false changed_when: false register: discovered_nftables_inputpolicy - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for hook forward deny policy" - ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook forward' + ansible.builtin.shell: | + nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook forward' failed_when: false changed_when: false register: discovered_nftables_forwardpolicy - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for hook output deny policy" - ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook output' + ansible.builtin.shell: | + nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook output' failed_when: false changed_when: false register: discovered_nftables_outputpolicy - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for SSH allow" - ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'ssh' + ansible.builtin.shell: | + nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'ssh' failed_when: false changed_when: false register: discovered_nftables_sshallowcheck @@ -177,19 +185,22 @@ - NIST800-55_CA-9 block: - name: "4.3.4 | AUDIT | Ensure nftables loopback traffic is configured | Gather iif lo accept existence | nftables" - ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'iif "lo" accept' + ansible.builtin.shell: | + nft list ruleset | awk '/hook input/,/}/' | grep 'iif "lo" accept' changed_when: false failed_when: false register: discovered_nftables_iiflo - name: "4.3.4 | AUDIT | Ensure nftables loopback traffic is configured | Gather ip saddr existence | nftables" - ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip saddr' + ansible.builtin.shell: | + nft list ruleset | awk '/hook input/,/}/' | grep 'ip saddr' changed_when: false failed_when: false register: discovered_nftables_ipsaddr - name: "4.3.4 | AUDIT | Ensure nftables loopback traffic is configured | Gather ip6 saddr existence | nftables" - ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip6 saddr' + ansible.builtin.shell: | + nft list ruleset | awk '/hook input/,/}/' | grep 'ip6 saddr' changed_when: false failed_when: false register: discovered_nftables_ip6saddr diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index 7923d50..eddf5ee 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -18,7 +18,7 @@ - rhel9cis_authselect_custom_profile_name not in prelim_authselect_current_profile.stdout or prelim_authselect_current_profile.stdout is not defined ansible.builtin.command: "/usr/bin/authselect create-profile {{ rhel9cis_authselect_custom_profile_name }} -b {{ rhel9cis_authselect_default_profile_to_copy }}" - changed_when: true + changed_when: false args: creates: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}" @@ -61,7 +61,8 @@ notify: Authselect update block: - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config" - ansible.builtin.shell: authselect current | grep faillock + ansible.builtin.shell: | + authselect current | grep faillock changed_when: false failed_when: discovered_authselect_current_faillock.rc not in [ 0, 1 ] register: discovered_authselect_current_faillock @@ -70,7 +71,6 @@ when: discovered_authselect_current_faillock.rc != 0 ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" changed_when: true - notify: Authselect update - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled" when: @@ -87,12 +87,13 @@ - rule_5.3.2.3 block: - name: "5.3.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Get current config" - ansible.builtin.shell: authselect current | grep quality + ansible.builtin.shell: | + authselect current | grep quality changed_when: false failed_when: discovered_authselect_current_quality.rc not in [ 0, 1 ] register: discovered_authselect_current_quality - - name: "5.3.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Add feature if missing" + - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled | Add feature if missing" when: discovered_authselect_current_quality.rc != 0 ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" changed_when: true @@ -113,7 +114,8 @@ - rule_5.3.2.4 block: - name: "5.3.2.4 | AUDIT | Ensure pam_pwhistory module is enabled | Get current config" - ansible.builtin.shell: authselect current | grep pwhistory + ansible.builtin.shell: | + authselect current | grep pwhistory changed_when: false failed_when: discovered_authselect_current_history.rc not in [ 0, 1 ] register: discovered_authselect_current_history diff --git a/tasks/section_5/cis_5.3.3.1.x.yml b/tasks/section_5/cis_5.3.3.1.x.yml index f7bfb64..19e1c44 100644 --- a/tasks/section_5/cis_5.3.3.1.x.yml +++ b/tasks/section_5/cis_5.3.3.1.x.yml @@ -101,7 +101,7 @@ line: "{{ rhel9cis_pamroot_lock_option }}" insertafter: '^# end of pam-auth-update config' create: true - mode: 'go-rwx' + mode: 'u-x,go-wx' - name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | remove lockout from pam files NOT AuthSelect" when: diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index 2363590..6a492e5 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -121,16 +121,17 @@ - rule_5.4.1.5 block: - name: "5.4.1.5 | AUDIT | Ensure inactive password lock is configured | Check current settings" - ansible.builtin.shell: useradd -D | grep INACTIVE={{ rhel9cis_inactivelock.lock_days }} | cut -f2 -d= + ansible.builtin.shell: | + useradd -D | grep INACTIVE={{ rhel9cis_inactivelock.lock_days }} | cut -f2 -d= changed_when: false failed_when: false check_mode: false register: discovered_passwdlck_inactive_settings - name: "5.4.1.5 | PATCH | Ensure inactive password lock is configured | Set default inactive setting" + when: discovered_passwdlck_inactive_settings.stdout | length == 0 ansible.builtin.command: useradd -D -f {{ rhel9cis_inactivelock.lock_days }} changed_when: true - when: discovered_passwdlck_inactive_settings.stdout | length == 0 - name: "5.4.1.5 | AUDIT | Ensure inactive password lock is 30 days or less | Getting user list" ansible.builtin.command: "awk -F: '/^[^#:]+:[^\\!\\*:]*:[^:]*:[^:]*:[^:]*:[^:]*:(\\s*|-1|3[1-9]|[4-9][0-9]|[1-9][0-9][0-9]+):[^:]*:[^:]*\\s*$/ {print $1}' /etc/shadow" diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index 0153820..ef15f1a 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -190,9 +190,7 @@ regexp: \s*umask line: "umask {{ rhel9cis_root_umask }}" create: true - owner: root - group: root - mode: 'go-rwx' + mode: 'u+x,go-rwx' - name: "5.4.2.7 | PATCH | Ensure system accounts do not have a valid login shell" when: diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 5896695..c000fe1 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -14,18 +14,41 @@ block: - name: "6.1.1 | PATCH | Ensure AIDE is installed" ansible.builtin.package: - name: aide + name: "{{ aide_packages }}" state: present - register: discovered_aide_installed + update_cache: true + register: discovered_aide_pkg_added - - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB" - when: discovered_aide_installed.changed # noqa no-handler + - name: "6.1.1 | PATCH | Ensure AIDE is installed | Recapture packages" + when: discovered_aide_pkg_added.skipped is not defined + ansible.builtin.package_facts: + manager: auto + + - name: "6.1.1 | AUDIT | Ensure AIDE is installed | Check file exists" + ansible.builtin.stat: + path: "{{ rhel9cis_aide_db_file }}" + register: discovered_aide_db_file + + - name: "6.1.1 | AUDIT | Ensure AIDE is installed | Check current db file age" + when: discovered_aide_db_file.stat.exists + ansible.builtin.find: + path: "{{ rhel9cis_aide_db_file | dirname }}" + pattern: "{{ rhel9cis_aide_db_file | basename }}" + age: "{{ rhel9cis_aide_db_file_age }}" + register: discovered_aide_db_age + + - name: "6.1.1 | PATCH | Ensure AIDE is installed | Configure AIDE" + when: + - not ansible_check_mode + - not discovered_aide_db_file.stat.exists or + (discovered_aide_db_age.files | length > 0) or + rhel9cis_aide_db_recreate block: - - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB" - ansible.builtin.command: /usr/sbin/aide --init + - name: "6.1.1 | PATCH | Ensure AIDE is installed | Build AIDE DB" + ansible.builtin.command: "{{ aide_initiate_command }}" changed_when: true - - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB | Wait for file before continuing" + - name: "6.1.1 | PATCH | Ensure AIDE is installed | Build AIDE DB | Wait for file before continuing" ansible.builtin.wait_for: path: /var/lib/aide/aide.db.new.gz @@ -34,7 +57,7 @@ src: /var/lib/aide/aide.db.new.gz dest: /var/lib/aide/aide.db.gz remote_src: true - mode: 'go-wx' + mode: 'ug-wx,o-rwx' - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked" when: diff --git a/tasks/section_6/cis_6.3.1.x.yml b/tasks/section_6/cis_6.3.1.x.yml index b27ba99..e795c83 100644 --- a/tasks/section_6/cis_6.3.1.x.yml +++ b/tasks/section_6/cis_6.3.1.x.yml @@ -1,8 +1,7 @@ --- - name: "6.3.1.1 | PATCH | Ensure auditd is installed" - when: - - rhel9cis_rule_6_3_1_1 + when: rhel9cis_rule_6_3_1_1 tags: - level2-server - level2-workstation @@ -87,7 +86,8 @@ - name: "6.3.1.3 | AUDIT | Ensure audit_backlog_limit is sufficient | Grubby update applied" when: discovered_reset_backlog_limits is defined - ansible.builtin.command: 'grubby --update-kernel=ALL --args="audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}"' + ansible.builtin.command: + cmd: 'grubby --update-kernel=ALL --args="audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}"' changed_when: true - name: "6.3.1.4 | PATCH | Ensure auditd service is enabled and active" diff --git a/tasks/section_6/cis_6.3.4.x.yml b/tasks/section_6/cis_6.3.4.x.yml index 806a1ec..74de70a 100644 --- a/tasks/section_6/cis_6.3.4.x.yml +++ b/tasks/section_6/cis_6.3.4.x.yml @@ -100,13 +100,7 @@ ansible.builtin.file: path: "{{ item }}" mode: 'go-w' - loop: - - /sbin/auditctl - - /sbin/aureport - - /sbin/ausearch - - /sbin/autrace - - /sbin/auditd - - /sbin/augenrules + loop: "{{ audit_bins }}" - name: "6.3.4.9 | PATCH | Ensure audit tools owner is configured" when: rhel9cis_rule_6_3_4_9 @@ -120,13 +114,7 @@ path: "{{ item }}" owner: root group: root - loop: - - /sbin/auditctl - - /sbin/aureport - - /sbin/ausearch - - /sbin/autrace - - /sbin/auditd - - /sbin/augenrules + loop: "{{ audit_bins }}" - name: "6.3.4.10 | PATCH | Ensure audit tools group owner is configured" when: rhel9cis_rule_6_3_4_10 @@ -140,10 +128,4 @@ ansible.builtin.file: path: "{{ item }}" group: root - loop: - - /sbin/auditctl - - /sbin/aureport - - /sbin/ausearch - - /sbin/autrace - - /sbin/auditd - - /sbin/augenrules + loop: "{{ audit_bins }}" diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml index 28c7fc6..2a33f33 100644 --- a/tasks/section_7/cis_7.2.x.yml +++ b/tasks/section_7/cis_7.2.x.yml @@ -243,7 +243,7 @@ state: directory owner: "{{ item.id }}" group: "{{ item.gid }}" - loop: "{{ rhel9cis_passwd | selectattr('uid', '>=', prelim_min_int_uid | int) | selectattr('uid', '<=', max_int_uid | int) | list }}" + loop: "{{ rhel9cis_passwd | selectattr('uid', '>=', prelim_min_int_uid | int) | selectattr('uid', '<=', prelim_max_int_uid | int) | list }}" loop_control: label: "{{ item.id }}" diff --git a/tasks/warning_facts.yml b/tasks/warning_facts.yml index b70a836..108cb89 100644 --- a/tasks/warning_facts.yml +++ b/tasks/warning_facts.yml @@ -13,7 +13,7 @@ # # warn_count the main variable for the number of warnings and each time a warn_control_id is added # the count increases by a value of 1 -- name: "{{ warn_control_id }} | AUDIT | Set fact for manual task warning." # noqa name[template] +- name: "{{ warn_control_id }} | AUDIT | Set fact for manual task warning." # noqa name[template] ansible.builtin.set_fact: warn_control_list: "{{ warn_control_list }} [{{ warn_control_id }}]" warn_count: "{{ warn_count | int + 1 }}" diff --git a/templates/audit/98_auditd_exception.rules.j2 b/templates/audit/98_auditd_exception.rules.j2 index 70ebd03..82f6555 100644 --- a/templates/audit/98_auditd_exception.rules.j2 +++ b/templates/audit/98_auditd_exception.rules.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown ### YOUR CHANGES WILL BE LOST! # This file contains users whose actions are not logged by auditd diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index e977e4e..6d69976 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown ### YOUR CHANGES WILL BE LOST! # This template will set all of the auditd configurations via a handler in the role in one task instead of individually diff --git a/templates/etc/cron.d/aide.cron.j2 b/templates/etc/cron.d/aide.cron.j2 index 4c1af92..f9324da 100644 --- a/templates/etc/cron.d/aide.cron.j2 +++ b/templates/etc/cron.d/aide.cron.j2 @@ -1,7 +1,7 @@ # Run AIDE integrity check ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown ### YOUR CHANGES WILL BE LOST! # CIS 1.3.2 diff --git a/templates/etc/dconf/db/00-automount_lock.j2 b/templates/etc/dconf/db/00-automount_lock.j2 index 0e55b5a..45989d0 100644 --- a/templates/etc/dconf/db/00-automount_lock.j2 +++ b/templates/etc/dconf/db/00-automount_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown # Lock desktop media-handling automount setting /org/gnome/desktop/media-handling/automount diff --git a/templates/etc/dconf/db/00-autorun_lock.j2 b/templates/etc/dconf/db/00-autorun_lock.j2 index cf9ed5d..60265c4 100644 --- a/templates/etc/dconf/db/00-autorun_lock.j2 +++ b/templates/etc/dconf/db/00-autorun_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown # Lock desktop media-handling settings /org/gnome/desktop/media-handling/autorun-never diff --git a/templates/etc/dconf/db/00-media-automount.j2 b/templates/etc/dconf/db/00-media-automount.j2 index 640538c..96c122f 100644 --- a/templates/etc/dconf/db/00-media-automount.j2 +++ b/templates/etc/dconf/db/00-media-automount.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown [org/gnome/desktop/media-handling] automount=false diff --git a/templates/etc/dconf/db/00-media-autorun.j2 b/templates/etc/dconf/db/00-media-autorun.j2 index 382469c..0e371af 100644 --- a/templates/etc/dconf/db/00-media-autorun.j2 +++ b/templates/etc/dconf/db/00-media-autorun.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown [org/gnome/desktop/media-handling] autorun-never=true diff --git a/templates/etc/dconf/db/00-screensaver.j2 b/templates/etc/dconf/db/00-screensaver.j2 index a747336..95237fb 100644 --- a/templates/etc/dconf/db/00-screensaver.j2 +++ b/templates/etc/dconf/db/00-screensaver.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown # Specify the dconf path [org/gnome/desktop/session] diff --git a/templates/etc/dconf/db/00-screensaver_lock.j2 b/templates/etc/dconf/db/00-screensaver_lock.j2 index 5988316..1b99027 100644 --- a/templates/etc/dconf/db/00-screensaver_lock.j2 +++ b/templates/etc/dconf/db/00-screensaver_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown # Lock desktop screensaver idle-delay setting /org/gnome/desktop/session/idle-delay diff --git a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 index 901e9e0..da31670 100644 --- a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 +++ b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown [org/gnome/login-screen] banner-message-enable=true diff --git a/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 index 6a9855a..c223c84 100644 --- a/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 +++ b/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 @@ -1,9 +1,9 @@ # CIS Configurations # 5.3.3.2.3 Ensure password complexity is configured -{% if rhel9cis_passwd_complex_option == 'minclass' %} +{% if rhel9cis_passwd_complex_option == 'minclass' %} # pragma: allowlist secret minclass = {{ rhel9cis_passwd_minclass }} {% endif %} -{% if rhel9cis_passwd_complex_option == 'credits' %} +{% if rhel9cis_passwd_complex_option == 'credits' %} # pragma: allowlist secret dcredit = {{rhel9cis_passwd_dcredit }} ucredit = {{ rhel9cis_passwd_ucredit }} ocredit = {{ rhel9cis_passwd_ocredit }} diff --git a/vars/main.yml b/vars/main.yml index ec72d0b..93439ad 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -44,3 +44,19 @@ container_vars_file: is_container.yml # rhel9cis is left off the front of this var for consistency in testing pipeline # system_is_ec2 toggle will disable tasks that fail on Amazon EC2 instances. Set true to skip and false to run tasks system_is_ec2: false + +# Aide Packages + +aide_packages: + - aide +# Aide initiate command for new DB creation +aide_initiate_command: /usr/sbin/aide --init + +# Audit vars +audit_bins: + - /sbin/auditctl + - /sbin/aureport + - /sbin/ausearch + - /sbin/autrace + - /sbin/auditd + - /sbin/augenrules