diff --git a/.ansible-lint b/.ansible-lint index f2a7e7c..f21e1f4 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -1,6 +1,9 @@ parseable: true quiet: true skip_list: + - 'schema' + - 'no-changed-when' + - 'fqcn-builtins' - '204' - '305' - '303' diff --git a/.github/workflows/github_vars.tfvars b/.github/workflows/github_vars.tfvars index e50753d..24daeca 100644 --- a/.github/workflows/github_vars.tfvars +++ b/.github/workflows/github_vars.tfvars @@ -8,7 +8,7 @@ environment = "lockdown_github_repo_workflow" // Matching pair name found in AWS for keypairs PEM key ami_key_pair_name = "github_actions" -private_key = "'.ssh/github_actions.pem'" +private_key = ".ssh/github_actions.pem" main_vpc_cidr = "172.22.0.0/24" public_subnets = "172.22.0.128/26" private_subnets = "172.22.0.192/26" diff --git a/.github/workflows/linux_benchmark_testing.yml b/.github/workflows/linux_benchmark_testing.yml index 5b2a708..908ea06 100644 --- a/.github/workflows/linux_benchmark_testing.yml +++ b/.github/workflows/linux_benchmark_testing.yml @@ -81,18 +81,9 @@ jobs: working-directory: .github/workflows run: cat hosts.yml -# Centos 7 images take a while to come up insert sleep or playbook fails +# Aws deployments taking a while to come up insert sleep or playbook fails - - name: Check if test os is rhel7 - working-directory: .github/workflows - id: test_os - run: >- - echo "::set-output name=RHEL7::$( - grep -c RHEL7 OS.tfvars - )" - - - name: if RHEL7 - Sleep for 60 seconds - #if: steps.test_os.outputs.RHEL7 >= 1 + - name: Sleep for 60 seconds run: sleep 60s shell: bash @@ -117,4 +108,4 @@ jobs: env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - run: terraform destroy -var-file "github_vars.tfvars" -var-file "OS.tfvars" --auto-approve -input=false + run: terraform destroy -var-file "github_vars.tfvars" -var-file "OS.tfvars" --auto-approve -input=false diff --git a/.yamllint b/.yamllint index fdea629..693eec6 100644 --- a/.yamllint +++ b/.yamllint @@ -2,22 +2,34 @@ ignore: | tests/ molecule/ + .github/ .gitlab-ci.yml *molecule.yml extends: default rules: - indentation: - # Requiring 4 space indentation - spaces: 4 - # Requiring consistent indentation within a file, either indented or not - indent-sequences: consistent - truthy: disable - braces: - max-spaces-inside: 1 - level: error - brackets: - max-spaces-inside: 1 - level: error - line-length: disable + indentation: + # Requiring 4 space indentation + spaces: 4 + # Requiring consistent indentation within a file, either indented or not + indent-sequences: consistent + truthy: disable + braces: + max-spaces-inside: 1 + level: error + brackets: + max-spaces-inside: 1 + level: error + indentation: + indent-sequences: consistent + level: error + line-length: disable + key-duplicates: enable + new-line-at-end-of-file: enable + new-lines: + type: unix + trailing-spaces: enable + truthy: + allowed-values: ['true', 'false'] + check-keys: false diff --git a/Changelog.md b/Changelog.md index ee9aff4..2fa85d4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,33 @@ # Changes to rhel9CIS +## 0.4 + +- Added assertion that ansible_user has password set for rule 5.3.4 +- RockyLinux now supported - release since initial branches +- gpg check updates +- audit out dir now /opt +- lint updates and improvements +- workflow updates and improvements moved to rocky image +- selinux regexp improvements +- warning summary now at end of play +- advanced auditd options to exclude users in POST section +- Issues fixed thanks to fgierlinger + - [#21](https://github.com/ansible-lockdown/RHEL9-CIS/issues/21) + - [#22](https://github.com/ansible-lockdown/RHEL9-CIS/issues/22) + +## 0.3 + +- update to auditd template + - uses facts and template new variable + - update_audit_template (default false) +- sysctl template updates and idempotency improvements +- container discovery usage improvements +- 3.4.1.5 discovery improvement +- 5.6.1.4 discovery improvement +- logrotate process logrotate.timer +- tidy up become: +- logic improvements + ## 0.2 - not all controls work with rhel8 releases any longer diff --git a/README.md b/README.md index 048c85f..4c7324b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Development Only -## RHEL 9 CIS (predicted) - ALPHA - CIS baselines or OS not yet GA +## RHEL 9 CIS (predicted) - Beta - CIS baselines or OS not yet GA ## Testing if you have access to the RH developer branches @@ -17,7 +17,7 @@ Based on [CIS RedHat Enterprise Linux 8 Benchmark v2.0.0. - 02-23-2022 ](https:/ ## Join us -On our [Discord Server](https://discord.gg/JFxpSgPFEJ) to ask questions, discuss features, or just chat with other Ansible-Lockdown users +On our [Discord Server](https://discord.io/ansible-lockdown) to ask questions, discuss features, or just chat with other Ansible-Lockdown users ## Caution(s) @@ -49,7 +49,9 @@ Refer to [RHEL9-CIS-Audit](https://github.com/ansible-lockdown/RHEL9-CIS-Audit). ## Requirements -RHEL 9 - Other versions are not supported. +RHEL 9 +Almalinux 9 +Rocky 9 - Access to download or add the goss binary and content to the system if using auditing (other options are available on how to get the content to the system.) diff --git a/defaults/main.yml b/defaults/main.yml index 6dfa404..510784b 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -369,7 +369,6 @@ rhel9cis_rh_sub_password: password # RedHat Satellite Subscription items rhel9cis_rhnsd_required: false - # 1.4.2 Bootloader password rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' rhel9cis_bootloader_password: random @@ -460,6 +459,11 @@ rhel9cis_tftp_client: false ## Section3 vars +## Sysctl +sysctl_update: false +flush_ipv4_route: false +flush_ipv6_route: false + ### Firewall Service - either firewalld, iptables, or nftables #### Some control allow for services to be removed or masked #### The options are under each heading @@ -498,6 +502,12 @@ rhel9cis_audit_back_log_limit: 8192 # The max_log_file parameter should be based on your sites policy rhel9cis_max_log_file_size: 10 +### 4.1.3.x audit template +update_audit_template: false + +## Advanced option found in auditd post +allow_auditd_uid_user_exclusions: false + ## Preferred method of logging ## Whether rsyslog or journald preferred method for local logging ## Affects rsyslog cis 4.2.1.3 and journald cis 4.2.2.5 @@ -633,8 +643,8 @@ audit_run_script_environment: ### Goss binary settings ### goss_version: - release: v0.3.16 - checksum: 'sha256:827e354b48f93bce933f5efcd1f00dc82569c42a179cf2d384b040d8a80bfbfb' + release: v0.3.18 + checksum: 'sha256:432308ebca0caf8165d45bd27e3262126aad9d15572ac8cb3149b3c91f75aace' audit_bin_path: /usr/local/bin/ audit_bin: "{{ audit_bin_path }}goss" audit_format: json @@ -651,7 +661,7 @@ copy_goss_from_path: /some/accessible/path ## managed by the control audit_content # git audit_file_git: "https://github.com/ansible-lockdown/{{ benchmark }}-Audit.git" -audit_git_version: main +audit_git_version: devel # copy: audit_local_copy: "some path to copy from" @@ -659,12 +669,9 @@ audit_local_copy: "some path to copy from" # get_url: audit_files_url: "some url maybe s3?" -# Where the goss audit configuration will be stored -audit_files: "/var/tmp/{{ benchmark }}-Audit/" - ## Goss configuration information # Where the goss configs and outputs are stored -audit_out_dir: '/var/tmp' +audit_out_dir: '/opt' audit_conf_dir: "{{ audit_out_dir }}/{{ benchmark }}-Audit/" pre_audit_outfile: "{{ audit_out_dir }}/{{ ansible_hostname }}_pre_scan_{{ ansible_date_time.epoch }}.{{ audit_format }}" post_audit_outfile: "{{ audit_out_dir }}/{{ ansible_hostname }}_post_scan_{{ ansible_date_time.epoch }}.{{ audit_format }}" diff --git a/handlers/main.yml b/handlers/main.yml index 08c8026..0fae419 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,14 +1,23 @@ --- # handlers file for RHEL9-CIS +- name: reload sysctl + shell: sysctl --system + args: + warn: false + when: + - sysctl_updated.changed + - name: sysctl flush ipv4 route table become: true sysctl: name: net.ipv4.route.flush value: '1' sysctl_set: true - ignore_errors: true - when: ansible_virtualization_type != "docker" + ignore_errors: true # noqa ignore-errors + when: + - flush_ipv4_route + - not system_is_container tags: - skip_ansible_lint @@ -18,35 +27,9 @@ name: net.ipv6.route.flush value: '1' sysctl_set: true - when: ansible_virtualization_type != "docker" - -- name: update sysctl - template: - src: "etc/sysctl.d/{{ item }}.j2" - dest: "/etc/sysctl.d/{{ item }}" - owner: root - group: root - mode: 0600 - notify: reload sysctl - with_items: - - 60-kernel_sysctl.conf - - 60-disable_ipv6.conf - - 60-netipv4_sysctl.conf - - 60-netipv6_sysctl.conf when: - - ansible_virtualization_type != "docker" - - "'procps-ng' in ansible_facts.packages" - -- name: reload sysctl - sysctl: - name: net.ipv4.route.flush - value: '1' - state: present - reload: true - ignoreerrors: true - when: - - ansible_virtualization_type != "docker" - - "'systemd' in ansible_facts.packages" + - flush_ipv6_route + - not system_is_container - name: systemd restart tmp.mount become: true @@ -72,53 +55,30 @@ warn: false - name: restart firewalld - become: true service: name: firewalld state: restarted - name: restart sshd - become: true service: name: sshd state: restarted - name: restart postfix - become: true service: name: postfix state: restarted - name: reload dconf - become: true shell: dconf update args: warn: false -- name: update auditd - template: - src: audit/99_auditd.rules.j2 - dest: /etc/audit/rules.d/99_auditd.rules - owner: root - group: root - mode: 0600 - notify: restart auditd - -- name: restart auditd - shell: /sbin/service auditd restart - changed_when: false - check_mode: false - failed_when: false - args: - warn: false - tags: - - skip_ansible_lint - - name: grub2cfg shell: "grub2-mkconfig -o /boot/grub2/grub.cfg" args: warn: false - ignore_errors: True + ignore_errors: true # noqa ignore-errors tags: - skip_ansible_lint @@ -142,6 +102,27 @@ systemd: daemon-reload: true +## Auditd tasks note order for handlers to run + +- name: auditd_immutable_check + shell: grep -c "^-e 2" /etc/audit/rules.d/99_auditd.rules + changed_when: false + register: auditd_immutable_check + +- name: audit_immutable_fact + debug: + msg: "Reboot required for auditd to apply new rules as immutable set" + notify: change_requires_reboot + when: + - auditd_immutable_check.stdout == '1' + +- name: restart auditd + shell: service auditd restart + args: + warn: false + tags: + - skip_ansible_lint + - name: change_requires_reboot set_fact: change_requires_reboot: true diff --git a/site.yml b/site.yml index 379549f..4446d3e 100644 --- a/site.yml +++ b/site.yml @@ -1,7 +1,6 @@ --- - hosts: all become: true - roles: - role: "{{ playbook_dir }}" diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index e4cac49..98f3855 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -22,7 +22,7 @@ - get_goss_file == 'copy' - name: install git if not present - package: + package: name: git state: present register: git_installed diff --git a/tasks/auditd.yml b/tasks/auditd.yml new file mode 100644 index 0000000..74830ca --- /dev/null +++ b/tasks/auditd.yml @@ -0,0 +1,26 @@ +--- + +- name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added + template: + src: audit/99_auditd.rules.j2 + dest: /etc/audit/rules.d/99_auditd.rules + owner: root + group: root + mode: 0600 + register: audit_rules_updated + notify: + - auditd_immutable_check + - audit_immutable_fact + - restart auditd + +- name: POST | Set up auditd user logging exceptions + template: + src: audit/98_auditd_exception.rules.j2 + dest: /etc/audit/rules.d/98_auditd_exceptions.rules + owner: root + group: root + mode: 0600 + notify: restart auditd + when: + - allow_auditd_uid_user_exclusions + - rhel9cis_auditd_uid_exclude | length > 0 diff --git a/tasks/main.yml b/tasks/main.yml index 1b240f7..0d272b1 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -20,6 +20,28 @@ tags: - always +- name: "Check password set for {{ ansible_user }}" + block: + - name: Capture current password state of "{{ ansible_user }}" + shell: "grep {{ ansible_user }} /etc/shadow | awk -F: '{print $2}'" + changed_when: false + failed_when: false + check_mode: false + register: ansible_user_password_set + + - name: "Assert that password set for {{ ansible_user }} and account not locked" + assert: + that: ansible_user_password_set.stdout | length != 0 and ansible_user_password_set.stdout != "!!" + fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_user }} has no password set - It can break access" + success_msg: "You a password set for the {{ ansible_user }}" + vars: + sudo_password_rule: rhel9cis_rule_5_3_4 + when: + - rhel9cis_rule_5_3_4 + - not system_is_ec2 + tags: + - user_passwd + - name: Setup rules if container block: - name: Discover and set container variable if required @@ -123,49 +145,49 @@ - name: run Section 1 tasks import_tasks: section_1/main.yml - become: true when: rhel9cis_section1 tags: - rhel9cis_section1 - name: run Section 2 tasks import_tasks: section_2/main.yml - become: true when: rhel9cis_section2 tags: - rhel9cis_section2 - name: run Section 3 tasks import_tasks: section_3/main.yml - become: true when: rhel9cis_section3 tags: - rhel9cis_section3 - name: run Section 4 tasks import_tasks: section_4/main.yml - become: true when: rhel9cis_section4 tags: - rhel9cis_section4 - name: run Section 5 tasks import_tasks: section_5/main.yml - become: true when: rhel9cis_section5 tags: - rhel9cis_section5 - name: run Section 6 tasks import_tasks: section_6/main.yml - become: true when: rhel9cis_section6 tags: - rhel9cis_section6 +- name: run auditd logic + import_tasks: auditd.yml + when: + - update_audit_template + tags: + - always + - name: run post remediation tasks import_tasks: post.yml - become: true tags: - post_tasks - always @@ -180,3 +202,10 @@ msg: "{{ audit_results.split('\n') }}" when: - run_audit + +- name: If Warnings found Output count and control IDs affected + debug: + msg: "You have {{ warn_count }} Warning(s) that require investigating that are related to the following benchmark ID(s) {{ control_number }}" + when: warn_count != 0 + tags: + - always diff --git a/tasks/post.yml b/tasks/post.yml index c0f6be8..3b5c3f2 100644 --- a/tasks/post.yml +++ b/tasks/post.yml @@ -12,57 +12,24 @@ tags: - always -- name: trigger update sysctl - shell: /bin/true - args: - warn: false - changed_when: true - check_mode: false - notify: update sysctl +- name: update sysctl + template: + src: "etc/sysctl.d/{{ item }}.j2" + dest: "/etc/sysctl.d/{{ item }}" + owner: root + group: root + mode: 0600 + register: sysctl_updated + notify: reload sysctl + with_items: + - 60-kernel_sysctl.conf + - 60-disable_ipv6.conf + - 60-netipv4_sysctl.conf + - 60-netipv6_sysctl.conf when: - - rhel9cis_rule_3_1_1 or - rhel9cis_rule_3_1_2 or - rhel9cis_rule_3_1_3 or - rhel9cis_rule_3_2_1 or - rhel9cis_rule_3_2_2 or - rhel9cis_rule_3_3_1 or - rhel9cis_rule_3_3_2 or - rhel9cis_rule_3_3_3 or - rhel9cis_rule_3_3_4 or - rhel9cis_rule_3_3_5 or - rhel9cis_rule_3_3_6 or - rhel9cis_rule_3_3_7 or - rhel9cis_rule_3_3_8 or - rhel9cis_rule_3_3_9 - tags: - - sysctl - -- name: trigger update auditd - shell: /bin/true - args: - warn: false - notify: update auditd - changed_when: true - check_mode: false - when: - - rhel9cis_rule_4_1_1_1 or - rhel9cis_rule_4_1_1_2 or - rhel9cis_rule_4_1_1_3 or - rhel9cis_rule_4_1_2_1 or - rhel9cis_rule_4_1_2_2 or - rhel9cis_rule_4_1_2_3 or - rhel9cis_rule_4_1_3 or - rhel9cis_rule_4_1_4 or - rhel9cis_rule_4_1_5 or - rhel9cis_rule_4_1_6 or - rhel9cis_rule_4_1_7 or - rhel9cis_rule_4_1_8 or - rhel9cis_rule_4_1_9 or - rhel9cis_rule_4_1_10 or - rhel9cis_rule_4_1_11 or - rhel9cis_rule_4_1_12 - tags: - - auditd + - sysctl_update + - not system_is_container + - "'procps-ng' in ansible_facts.packages" - name: flush handlers meta: flush_handlers @@ -77,11 +44,20 @@ - name: POST | Warning a reboot required but skip option set debug: - msg: "Warning! changes have been made that require a reboot to be implemented but skip reboot was set - Can affect compliance check results" + 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" + set_fact: + control_number: "{{ control_number }} + [ 'Reboot_required' ]" + warn_count: "{{ warn_count | int + 1 }}" + when: + - change_requires_reboot + - skip_reboot + tags: - grub - level1-server diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 0ab61b2..4429b7e 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -2,7 +2,7 @@ - name: "Post Audit | Run post_remediation {{ benchmark }} audit" shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ post_audit_outfile }} -g {{ group_names }}" - environment: "{{ audit_run_script_environment|default({}) }}" + environment: "{{ audit_run_script_environment | default({}) }}" changed_when: audit_run_post_remediation.rc == 0 register: audit_run_post_remediation args: @@ -28,7 +28,7 @@ - name: Capture post-audit result set_fact: - post_audit_summary: "{{ post_audit.stdout | from_json |json_query(summary) }}" + post_audit_summary: "{{ post_audit.stdout | from_json | json_query(summary) }}" vars: summary: 'summary."summary-line"' when: diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index bb9344a..93c4985 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -33,6 +33,9 @@ get_url: url: "{{ audit_files_url }}" dest: "{{ audit_conf_dir }}" + owner: root + group: root + mode: 0755 when: - audit_content == 'get_url' @@ -70,7 +73,7 @@ - name: "Pre Audit | Run pre_remediation {{ benchmark }} audit" shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ pre_audit_outfile }} -g {{ group_names }}" - environment: "{{ audit_run_script_environment|default({}) }}" + environment: "{{ audit_run_script_environment | default({}) }}" changed_when: audit_run_pre_remediation.rc == 0 register: audit_run_pre_remediation args: @@ -87,7 +90,7 @@ - name: Pre Audit | Capture pre-audit result set_fact: - pre_audit_summary: "{{ pre_audit.stdout | from_json |json_query(summary) }}" + pre_audit_summary: "{{ pre_audit.stdout | from_json | json_query(summary) }}" vars: summary: 'summary."summary-line"' when: diff --git a/tasks/prelim.yml b/tasks/prelim.yml index eb17d00..80a273b 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -82,6 +82,31 @@ - level1-server - level1-workstation +- name: "PRELIM | Ensure python3-libselinux is installed" + 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" + stat: + path: /sys/firmware/efi + register: rhel_09_efi_boot + + - name: "PRELIM | AUDIT | set legacy boot and grub path | Bios" + 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" + set_fact: + grub2_path: /etc/grub2-efi.cfg + when: rhel_09_efi_boot.stat.exists + - name: "PRELIM | Section 4.1 | Configure System Accounting (auditd)" package: name: audit @@ -191,7 +216,9 @@ min_int_uid: "{{ uid_min_id.stdout }}" max_int_uid: "{{ uid_max_id.stdout }}" min_int_gid: "{{ gid_min_id.stdout }}" -- debug: + +- name: Output of uid findings + debug: msg: "{{ min_int_uid }} {{ max_int_uid }}" when: diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index f687901..1c99b62 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -7,14 +7,14 @@ path: /etc/modprobe.d/CIS.conf regexp: "^(#)?install cramfs(\\s|$)" line: "install cramfs /bin/true" - create: yes + create: true mode: 0600 - name: "1.1.1.1 | PATCH | Ensure mounting of cramfs filesystems is disabled | Disable cramfs" modprobe: name: cramfs state: absent - when: ansible_connection != 'docker' + when: not system_is_container when: - rhel9cis_rule_1_1_1_1 tags: @@ -32,14 +32,14 @@ path: /etc/modprobe.d/CIS.conf regexp: "^(#)?install squashfs(\\s|$)" line: "install squashfs /bin/true" - create: yes + create: true mode: 0600 - name: "1.1.1.2 | PATCH | Ensure mounting of squashfs filesystems is disabled | Disable squashfs" modprobe: name: squashfs state: absent - when: ansible_connection != 'docker' + when: not system_is_container when: - rhel9cis_rule_1_1_1_2 tags: @@ -57,14 +57,14 @@ path: /etc/modprobe.d/CIS.conf regexp: "^(#)?install udf(\\s|$)" line: "install udf /bin/true" - create: yes + create: true mode: 0600 - name: "1.1.1.3 | PATCH | Ensure mounting of udf filesystems is disable | Disable udf" modprobe: name: udf state: absent - when: ansible_connection != 'docker' + when: not system_is_container when: - rhel9cis_rule_1_1_1_3 tags: diff --git a/tasks/section_1/cis_1.1.2.x.yml b/tasks/section_1/cis_1.1.2.x.yml index a50797d..d7db5a6 100644 --- a/tasks/section_1/cis_1.1.2.x.yml +++ b/tasks/section_1/cis_1.1.2.x.yml @@ -1,11 +1,30 @@ --- - name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition" - debug: - msg: "Warning! /tmp is not mounted on a separate partition" + block: + - name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition | Absent" + debug: + msg: "Warning!! /tmp is not mounted on a separate partition" + when: + - required_mount not in mount_names + + - name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition | Warn Count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_1.1.2.1' ]" + warn_count: "{{ warn_count | int + 1 }}" + when: + - required_mount not in mount_names + + - name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var | Present" + debug: + msg: "Congratulations: {{ required_mount }} exists." + register: var_mount_present + when: + - required_mount in mount_names + vars: + required_mount: '/tmp' when: - rhel9cis_rule_1_1_2_1 - - ansible_mounts | selectattr('mount', 'match', '^/tmp$') | list | length == 0 tags: - level1-server - level1-workstation @@ -68,7 +87,6 @@ tags: - level1-server - level1-workstation - - scored - patch - mounts - rule_1.1.2.1 diff --git a/tasks/section_1/cis_1.1.3.x.yml b/tasks/section_1/cis_1.1.3.x.yml index 8fa9e4b..9e4feb8 100644 --- a/tasks/section_1/cis_1.1.3.x.yml +++ b/tasks/section_1/cis_1.1.3.x.yml @@ -4,12 +4,19 @@ block: - name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var | Absent" debug: - msg: "Warning! {{ required_mount }} doesn't exist. This is a manual task" + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" register: var_mount_absent changed_when: var_mount_absent.skipped is undefined when: - required_mount not in mount_names + - name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var | Warn Count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_1.1.3.1' ]" + warn_count: "{{ warn_count | int + 1 }}" + when: + - required_mount not in mount_names + - name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var | Present" debug: msg: "Congratulations: {{ required_mount }} exists." @@ -38,7 +45,7 @@ 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 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_3_4 %}nosuid{% endif %} + opts: defaults,{% if rhel9cis_rule_1_1_3_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_3_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_3_4 %}nosuid{% endif %} with_items: - "{{ ansible_mounts }}" loop_control: diff --git a/tasks/section_1/cis_1.1.4.x.yml b/tasks/section_1/cis_1.1.4.x.yml index c780013..d05db6a 100644 --- a/tasks/section_1/cis_1.1.4.x.yml +++ b/tasks/section_1/cis_1.1.4.x.yml @@ -5,12 +5,19 @@ block: - name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp | Absent" debug: - msg: "Warning! {{ required_mount }} doesn't exist. This is a manual task" + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" register: var_tmp_mount_absent changed_when: var_tmp_mount_absent.skipped is undefined when: - required_mount not in mount_names + - name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp | Warn Count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_1.1.4.1' ]" + warn_count: "{{ warn_count | int + 1 }}" + when: + - required_mount not in mount_names + - name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp | Present" debug: msg: "Congratulations: {{ required_mount }} exists." @@ -39,7 +46,7 @@ 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 %} + opts: defaults,{% if rhel9cis_rule_1_1_4_2 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_4_4 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_4_3 %}nosuid{% endif %} with_items: - "{{ ansible_mounts }}" loop_control: diff --git a/tasks/section_1/cis_1.1.5.x.yml b/tasks/section_1/cis_1.1.5.x.yml index c9343c4..dd4ab9f 100644 --- a/tasks/section_1/cis_1.1.5.x.yml +++ b/tasks/section_1/cis_1.1.5.x.yml @@ -4,11 +4,19 @@ block: - name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log | Absent" debug: - msg: "Warning! {{ required_mount }} doesn't exist. This is a manual task" + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" register: var_log_mount_absent changed_when: var_log_mount_absent.skipped is undefined when: - required_mount not in mount_names + + - name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log | Warn Count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_1.1.5.1' ]" + warn_count: "{{ warn_count | int + 1 }}" + when: + - required_mount not in mount_names + - name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log | Present" debug: msg: "Congratulations: {{ required_mount }} exists." @@ -37,7 +45,7 @@ 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 %} + opts: defaults,{% if rhel9cis_rule_1_1_5_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_5_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_5_4 %}nosuid{% endif %} with_items: - "{{ ansible_mounts }}" loop_control: diff --git a/tasks/section_1/cis_1.1.6.x.yml b/tasks/section_1/cis_1.1.6.x.yml index 1df3e84..afbe41a 100644 --- a/tasks/section_1/cis_1.1.6.x.yml +++ b/tasks/section_1/cis_1.1.6.x.yml @@ -4,11 +4,19 @@ block: - name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Absent" debug: - msg: "Warning! {{ required_mount }} doesn't exist. This is a manual task" + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" register: var_log_audit_mount_absent changed_when: var_log_audit_mount_absent.skipped is undefined when: - required_mount not in mount_names + + - name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Warn Count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_1.1.6.1' ]" + warn_count: "{{ warn_count | int + 1 }}" + when: + - required_mount not in mount_names + - name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Present" debug: msg: "Congratulations: {{ required_mount }} exists." diff --git a/tasks/section_1/cis_1.1.7.x.yml b/tasks/section_1/cis_1.1.7.x.yml index 453fef5..59f28ba 100644 --- a/tasks/section_1/cis_1.1.7.x.yml +++ b/tasks/section_1/cis_1.1.7.x.yml @@ -4,11 +4,19 @@ block: - name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home | Absent" debug: - msg: "Warning! {{ required_mount }} doesn't exist. This is a manual task" + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" register: home_mount_absent changed_when: home_mount_absent.skipped is undefined when: - required_mount not in mount_names + + - name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home | Warn Count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_1.1.7.1' ]" + warn_count: "{{ warn_count | int + 1 }}" + when: + - required_mount not in mount_names + - name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home | Present" debug: msg: "Congratulations: {{ required_mount }} exists." diff --git a/tasks/section_1/cis_1.1.8.x.yml b/tasks/section_1/cis_1.1.8.x.yml index 75bdabb..26ae877 100644 --- a/tasks/section_1/cis_1.1.8.x.yml +++ b/tasks/section_1/cis_1.1.8.x.yml @@ -13,7 +13,7 @@ shell: mount -l | grep -E '\s/dev/shm\s' changed_when: false failed_when: false - check_mode: no + check_mode: false register: rhel9cis_1_1_8_x_dev_shm_status - name: | @@ -25,7 +25,7 @@ src: tmpfs fstype: tmpfs state: mounted - opts: defaults,{% if rhel9cis_rule_1_1_8_1 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_8_2 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_8_3 %}nosuid{% endif %} + opts: defaults,{% if rhel9cis_rule_1_1_8_2 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_8_1 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_8_3 %}nosuid{% endif %} when: "'dev/shm' in rhel9cis_1_1_8_x_dev_shm_status.stdout" notify: change_requires_reboot when: diff --git a/tasks/section_1/cis_1.1.x.yml b/tasks/section_1/cis_1.1.x.yml index a77e524..ea5c862 100644 --- a/tasks/section_1/cis_1.1.x.yml +++ b/tasks/section_1/cis_1.1.x.yml @@ -3,7 +3,7 @@ - name: "1.1.9 | PATCH | Disable Automounting" service: name: autofs - enabled: no + enabled: false when: - not rhel9cis_allow_autofs - "'autofs' in ansible_facts.packages" @@ -24,7 +24,7 @@ path: /etc/modprobe.d/CIS.conf regexp: "^(#)?install usb-storage(\\s|$)" line: "install usb-storage /bin/true" - create: yes + create: true owner: root group: root mode: 0600 diff --git a/tasks/section_1/cis_1.2.x.yml b/tasks/section_1/cis_1.2.x.yml index 960815f..9445d15 100644 --- a/tasks/section_1/cis_1.2.x.yml +++ b/tasks/section_1/cis_1.2.x.yml @@ -20,12 +20,38 @@ - skip_ansible_lint # Added as no_log still errors on ansuible-lint - name: "1.2.2 | AUDIT | Ensure GPG keys are configured" - shell: "PKG=`rpm -qf {{ rpm_gpg_key }}` && rpm -q --queryformat \"%{PACKAGER} %{SIGPGP:pgpsig}\\n\" \"${PKG}\" | grep \"^{{ rpm_packager }}.*Key.ID.{{ rpm_key }}\"" - changed_when: false + block: + - name: "1.2.2 | AUDIT | Ensure GPG keys are configured | list installed pubkey keys" + shell: "rpm -qa | grep {{ os_gpg_key_pubkey_name }}" + changed_when: false + failed_when: false + register: os_installed_pub_keys + + - name: "1.2.2 | AUDIT | Ensure GPG keys are configured | Query found keys" + 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.2 | AUDIT | Ensure GPG keys are configured | expected keys pass" + debug: + msg: "Congratulations !! - The installed gpg keys match expected values" + when: + - os_installed_pub_keys.rc == 0 + - os_gpg_key_check.rc == 0 + + - name: "1.2.2 | AUDIT | Ensure GPG keys are configured | expected keys fail" + fail: + msg: Installed GPG Keys do not meet expected values or keys installed that are not expected + when: + - os_installed_pub_keys.rc == 1 or + os_gpg_key_check.rc == 1 when: - rhel9cis_rule_1_2_2 - ansible_distribution == "RedHat" or - ansible_distribution == "Rocky" + ansible_distribution == "Rocky" or + ansible_distribution == "AlmaLinux" tags: - level1-server - level1-workstation @@ -45,7 +71,7 @@ - name: "1.2.3 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos" replace: name: "{{ item.path }}" - regexp: '^gpgcheck\s+=\s+0' + regexp: "^gpgcheck=0" replace: "gpgcheck=1" with_items: - "{{ yum_repos.files }}" @@ -67,15 +93,20 @@ changed_when: false failed_when: false register: dnf_configured - check_mode: no + check_mode: false args: warn: false - name: "1.2.4 | AUDIT | Ensure package manager repositories are configured | Display repo list" debug: msg: - - "Warning! Below are the configured repos. Please review and make sure all align with site policy" + - "Warning!! Below are the configured repos. Please review and make sure all align with site policy" - "{{ dnf_configured.stdout_lines }}" + + - name: "1.2.4 | AUDIT | Ensure package manager repositories are configured | Warn Count" + set_fact: + control_number: "{{ control_number }} + ['rule_1.2.4']" + warn_count: "{{ warn_count | int + 1 }}" when: - rhel9cis_rule_1_2_4 tags: diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index 6ac4979..8ba419e 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -58,7 +58,7 @@ path: /etc/systemd/system/rescue.service.d/00-require-auth.conf regexp: '^ExecStart=' line: "ExecStart=-/usr/lib/systemd/systemd-sulogin-shell rescue" - create: yes + create: true owner: root group: root mode: 0644 diff --git a/tasks/section_1/cis_1.5.x.yml b/tasks/section_1/cis_1.5.x.yml index 6573e51..031ba5c 100644 --- a/tasks/section_1/cis_1.5.x.yml +++ b/tasks/section_1/cis_1.5.x.yml @@ -32,10 +32,13 @@ - rule_1.5.2 - name: "1.5.3 | PATCH | Ensure address space layout randomization (ASLR) is enabled" - debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-kernel_sysctl.conf" - notify: - - update sysctl + block: + - name: "1.5.3 | PATCH | Ensure address space layout randomization (ASLR) is enabled" + set_fact: + sysctl_update: true + - name: "1.5.3 | PATCH | Ensure address space layout randomization (ASLR) is enabled" + debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-kernel_sysctl.conf" when: - rhel9cis_rule_1_5_3 tags: diff --git a/tasks/section_1/cis_1.6.1.x.yml b/tasks/section_1/cis_1.6.1.x.yml index f917a99..9a8d134 100644 --- a/tasks/section_1/cis_1.6.1.x.yml +++ b/tasks/section_1/cis_1.6.1.x.yml @@ -16,10 +16,10 @@ - name: "1.6.1.2 | PATCH | Ensure SELinux is not disabled in bootloader configuration" replace: dest: /etc/default/grub - regexp: '(selinux|enforcing)\s*=(\s0|0).*' + regexp: 'selinux=0' replace: '' register: selinux_grub_patch - ignore_errors: yes + ignore_errors: true # noqa ignore-errors notify: grub2cfg when: - rhel9cis_rule_1_6_1_2 @@ -78,7 +78,13 @@ - name: "1.6.1.5 | AUDIT | Ensure no unconfined services exist | Message on unconfined services" debug: - msg: "Warning! You have unconfined services: {{ rhelcis_1_6_1_5_unconf_services.stdout_lines }}" + msg: "Warning!! You have unconfined services: {{ rhelcis_1_6_1_5_unconf_services.stdout_lines }}" + when: rhelcis_1_6_1_5_unconf_services.stdout | length > 0 + + - name: "1.6.1.5 | AUDIT | Ensure no unconfined services exist | warning count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_1.6.1.5' ]" + warn_count: "{{ warn_count | int + 1 }}" when: rhelcis_1_6_1_5_unconf_services.stdout | length > 0 when: - rhel9cis_rule_1_6_1_5 diff --git a/tasks/section_1/cis_1.8.x.yml b/tasks/section_1/cis_1.8.x.yml index a126a0a..f47d2a1 100644 --- a/tasks/section_1/cis_1.8.x.yml +++ b/tasks/section_1/cis_1.8.x.yml @@ -21,7 +21,7 @@ regexp: "{{ item.regexp }}" line: "{{ item.line }}" state: present - create: yes + create: true owner: root group: root mode: 0644 @@ -50,7 +50,7 @@ path: "{{ item.file }}" regexp: "{{ item.regexp }}" line: "{{ item.line }}" - create: yes + create: true owner: root group: root mode: 0644 @@ -93,7 +93,10 @@ path: /etc/dconf/db/local.d/00-media-automount regexp: "{{ item.regex }}" line: "{{ item.line }}" - create: yes + create: true + owner: root + group: root + mode: 0644 notify: reload dconf with_items: - { regex: '\[org\/gnome\/desktop\/media-handling\]', line: '[org/gnome/desktop/media-handling]' } diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index effe806..1db8179 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -29,7 +29,7 @@ path: /etc/sysconfig/chronyd regexp: "^(#)?OPTIONS" line: "OPTIONS=\"-u chrony\"" - create: yes + create: true mode: 0644 when: - rhel9cis_rule_2_1_2 diff --git a/tasks/section_2/cis_2.4.yml b/tasks/section_2/cis_2.4.yml index e17ab76..3373e54 100644 --- a/tasks/section_2/cis_2.4.yml +++ b/tasks/section_2/cis_2.4.yml @@ -6,15 +6,20 @@ shell: systemctl list-units --type=service changed_when: false failed_when: false - check_mode: no + check_mode: false register: rhel9cis_2_4_services - name: "2.4 | AUDIT | Ensure nonessential services are removed or masked | Display list of services" debug: msg: - - "Warning! Below are the list of services, both active and inactive" + - "Warning!! Below are the list of services, both active and inactive" - "Please review to make sure all are essential" - "{{ rhel9cis_2_4_services.stdout_lines }}" + + - name: "2.4 | AUDIT | Ensure nonessential services are removed or masked | Warn Count" + set_fact: + control_number: "{{ control_number }} + ['rule_2.4']" + warn_count: "{{ warn_count | int + 1 }}" when: - rhel9cis_rule_2_4 tags: diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index db3c0fd..6eaf58f 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -3,11 +3,15 @@ # The CIS Control wants IPv6 disabled if not in use. # We are using the rhel9cis_ipv6_required to specify if you have IPv6 in use - name: "3.1.1 | PATCH | Verify if IPv6 is enabled on the system" - debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-disable_ipv6.conf" - notify: - - update sysctl - - sysctl flush ipv6 route table + block: + - name: "3.1.1 | PATCH | Verify if IPv6 is enabled on the system" + set_fact: + sysctl_update: true + flush_ipv6_route: true + + - name: "3.1.1 | PATCH | Verify if IPv6 is enabled on the system" + debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-disable_ipv6.conf" when: - not rhel9cis_ipv6_required - rhel9cis_rule_3_1_1 @@ -64,9 +68,9 @@ command: rpm -q NetworkManager changed_when: false failed_when: false - check_mode: no + check_mode: false args: - warn: no + warn: false register: rhel_08_nmcli_available - name: "3.1.4 | AUDIT | Ensure wireless interfaces are disabled | Check if wifi is enabled" diff --git a/tasks/section_3/cis_3.2.x.yml b/tasks/section_3/cis_3.2.x.yml index 46295ec..6e07c55 100644 --- a/tasks/section_3/cis_3.2.x.yml +++ b/tasks/section_3/cis_3.2.x.yml @@ -2,19 +2,25 @@ - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled" block: + - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv4 forwarding | Set Fact" + set_fact: + sysctl_update: true + flush_ipv4_route: true + - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv4 forwarding" debug: msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - notify: - - update sysctl - - sysctl flush ipv4 route table - - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding" - debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" - notify: - - update sysctl - - sysctl flush ipv6 route table + - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | IPv6" + block: + - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding | Set Fact" + set_fact: + flush_ipv6_route: true + + - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding" + debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" + when: rhel9cis_ipv6_required when: - not rhel9cis_is_router @@ -28,11 +34,14 @@ - rule_3.2.1 - name: "3.2.2 | PATCH | Ensure packet redirect sending is disabled" - debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - notify: - - update sysctl - - sysctl flush ipv4 route table + block: + - name: "3.2.2 | PATCH | Ensure packet redirect sending is disabled | Set Fact" + set_fact: + sysctl_update: true + flush_ipv4_route: true + - name: "3.2.2 | PATCH | Ensure packet redirect sending is disabled" + debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" when: - not rhel9cis_is_router - rhel9cis_rule_3_2_2 diff --git a/tasks/section_3/cis_3.3.x.yml b/tasks/section_3/cis_3.3.x.yml index 139ca65..b78593e 100644 --- a/tasks/section_3/cis_3.3.x.yml +++ b/tasks/section_3/cis_3.3.x.yml @@ -2,19 +2,23 @@ - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted" block: - - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted" + - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | IPv4 | Set Fact" + set_fact: + sysctl_update: true + flush_ipv4_route: true + - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | IPv4" debug: msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - notify: - - update sysctl - - sysctl flush ipv4 route table - - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted" - debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" - notify: - - sysctl flush ipv6 route table - - update sysctl + - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | IPv6" + block: + - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | IPv6 | Set Fact" + set_fact: + flush_ipv6_route: true + + - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | IPv6" + debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" when: rhel9cis_ipv6_required when: - rhel9cis_rule_3_3_1 @@ -27,19 +31,24 @@ - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted" block: - - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted" + - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv4 | Set Fact" + set_fact: + sysctl_update: true + flush_ipv4_route: true + + - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv4" debug: msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - notify: - - update sysctl - - sysctl flush ipv4 route table - - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted" - debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" - notify: - - sysctl flush ipv6 route table - - update sysctl + - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv6" + block: + - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv6 | Set Fact" + set_fact: + flush_ipv6_route: true + + - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv6" + debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" when: rhel9cis_ipv6_required when: - rhel9cis_rule_3_3_2 @@ -51,9 +60,15 @@ - rule_3.3.2 - name: "3.3.3 | PATCH | Ensure secure ICMP redirects are not accepted" - debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - notify: update sysctl + block: + - name: "3.3.3 | PATCH | Ensure secure ICMP redirects are not accepted | Set Fact" + set_fact: + sysctl_update: true + flush_ipv4_route: true + + - name: "3.3.3 | PATCH | Ensure secure ICMP redirects are not accepted" + debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" when: - rhel9cis_rule_3_3_3 tags: @@ -64,9 +79,15 @@ - rule_3.3.3 - name: "3.3.4 | PATCH | Ensure suspicious packets are logged" - debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - notify: update sysctl + block: + - name: "3.3.4 | PATCH | Ensure suspicious packets are logged | Set Fact" + set_fact: + sysctl_update: true + flush_ipv4_route: true + + - name: "3.3.4 | PATCH | Ensure suspicious packets are logged" + debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" when: - rhel9cis_rule_3_3_4 tags: @@ -77,9 +98,15 @@ - rule_3.3.4 - name: "3.3.5 | PATCH | Ensure broadcast ICMP requests are ignored" - debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - notify: update sysctl + block: + - name: "3.3.5 | PATCH | Ensure broadcast ICMP requests are ignored | Set Fact" + set_fact: + sysctl_update: true + flush_ipv4_route: true + + - name: 3.3.5 | PATCH | Ensure broadcast ICMP requests are ignored" + debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" when: - rhel9cis_rule_3_3_5 tags: @@ -90,9 +117,15 @@ - rule_3.3.5 - name: "3.3.6 | PATCH | Ensure bogus ICMP responses are ignored" - debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - notify: update sysctl + block: + - name: "3.3.6 | PATCH | Ensure bogus ICMP responses are ignored | Set Fact" + set_fact: + sysctl_update: true + flush_ipv4_route: true + + - name: "3.3.6 | PATCH | Ensure bogus ICMP responses are ignored" + debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" when: - rhel9cis_rule_3_3_6 tags: @@ -103,9 +136,15 @@ - rule_3.3.6 - name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled" - debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - notify: update sysctl + block: + - name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled | Set Fact" + set_fact: + sysctl_update: true + flush_ipv4_route: true + + - name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled" + debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" when: - rhel9cis_rule_3_3_7 tags: @@ -116,9 +155,15 @@ - rule_3.3.7 - name: "3.3.8 | PATCH | Ensure TCP SYN Cookies is enabled" - debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - notify: update sysctl + block: + - name: "3.3.8 | PATCH | Ensure TCP SYN Cookies is enabled | Set Fact" + set_fact: + sysctl_update: true + flush_ipv4_route: true + + - name: "3.3.8 | PATCH | Ensure TCP SYN Cookies is enabled" + debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" when: - rhel9cis_rule_3_3_8 tags: @@ -130,20 +175,14 @@ - name: "3.3.9 | PATCH | Ensure IPv6 router advertisements are not accepted" block: - - name: "3.3.9 | PATCH | Ensure IPv6 router advertisements are not accepted" - debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - notify: - - update sysctl - - sysctl flush ipv4 route table + - name: "3.3.9 | PATCH | Ensure IPv6 router advertisements are not accepted | IPv6 | Set Fact" + set_fact: + sysctl_update: true + flush_ipv6_route: true - - name: "3.3.9 | PATCH | Ensure IPv6 router advertisements are not accepted" + - name: "3.3.9 | PATCH | Ensure IPv6 router advertisements are not accepted | IPv6" debug: msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl" - notify: - - sysctl flush ipv6 route table - - update sysctl - when: rhel9cis_ipv6_required when: - rhel9cis_ipv6_required - rhel9cis_rule_3_3_9 diff --git a/tasks/section_3/cis_3.4.1.x.yml b/tasks/section_3/cis_3.4.1.x.yml index caabdb5..d43dfe6 100644 --- a/tasks/section_3/cis_3.4.1.x.yml +++ b/tasks/section_3/cis_3.4.1.x.yml @@ -49,7 +49,7 @@ systemd: name: nftables state: stopped - masked: yes + masked: true when: - rhel9cis_firewalld_nftables_state == "masked" @@ -73,7 +73,7 @@ systemd: name: firewalld state: started - enabled: yes + enabled: true when: - rhel9cis_rule_3_4_1_4 tags: @@ -83,10 +83,20 @@ - patch - firewalld - rule_3_4_1_4 - - name: "3.4.1.5 | PATCH | Ensure firewalld default zone is set" - command: firewall-cmd --set-default-zone="{{ rhel9cis_default_zone }}" + block: + - name: "3.4.1.5 | AUDIT | Ensure firewalld default zone is set" + shell: "firewall-cmd --get-default-zone | grep {{ rhel9cis_default_zone }}" + changed_when: false + failed_when: ( firewalld_zone_set.rc not in [ 0, 1 ] ) + register: firewalld_zone_set + + - name: "3.4.1.5 | AUDIT | Ensure firewalld default zone is set" + command: firewall-cmd --set-default-zone="{{ rhel9cis_default_zone }}" + when: + - firewalld_zone_set.rc != 0 when: + - rhel9cis_firewall == "firewalld" - rhel9cis_rule_3_4_1_5 tags: - level1-server @@ -102,7 +112,7 @@ shell: "nmcli -t connection show | awk -F: '{ if($4){print $4} }' | while read INT; do firewall-cmd --get-active-zones | grep -B1 $INT; done" changed_when: false failed_when: false - check_mode: no + check_mode: false register: rhel9cis_3_4_1_6_interfacepolicy - name: "3.4.1.6 | AUDIT | Ensure network interfaces are assigned to appropriate zone | Get list of interfaces and polocies | Show the interface to policy" @@ -125,7 +135,7 @@ shell: "firewall-cmd --get-active-zones | awk '!/:/ {print $1}' | while read ZN; do firewall-cmd --list-all --zone=$ZN; done" changed_when: false failed_when: false - check_mode: no + check_mode: false register: rhel9cis_3_4_1_7_servicesport - name: "3.4.1.7 | AUDIT | Ensure firewalld drops unnecessary services and ports | Show services and ports" diff --git a/tasks/section_3/cis_3.4.2.x.yml b/tasks/section_3/cis_3.4.2.x.yml index a9284c5..ebb3631 100644 --- a/tasks/section_3/cis_3.4.2.x.yml +++ b/tasks/section_3/cis_3.4.2.x.yml @@ -5,6 +5,7 @@ name: nftables state: present when: + - rhel9cis_firewall == "nftables" - rhel9cis_rule_3_4_2_1 tags: - level1-server @@ -17,22 +18,11 @@ # The control allows the service it be masked or not installed # We have chosen not installed - name: "3.4.2.2 | PATCH | Ensure firewalld is either not installed or masked with nftables" - block: - - name: "3.4.2.2 | PATCH | Ensure firewalld is either not installed or masked with nftables | mask service" - systemd: - name: firewalld - masked: true - state: stopped - when: - - rhel9cis_nftables_firewalld_state == "masked" - - - name: "3.4.2.2 | PATCH | Ensure firewalld is either not installed or masked with nftables | pkg removed" - package: - name: firewalld - state: absent - when: - - rhel9cis_nftables_firewalld_state == "absent" + package: + name: firewalld + state: absent when: + - rhel9cis_firewall == "nftables" - rhel9cis_rule_3_4_2_2 tags: - level1-server @@ -49,7 +39,7 @@ name: "{{ item }}" enabled: false masked: true - ignore_errors: true + ignore_errors: true # noqa ignore-errors with_items: - iptables - ip6tables @@ -59,6 +49,7 @@ name: iptables-service state: absent when: + - rhel9cis_firewall == "nftables" - rhel9cis_rule_3_4_2_3 tags: - level1-server @@ -105,17 +96,26 @@ - name: "3.4.2.5 | AUDIT | Ensure an nftables table exists | Alert on no tables" debug: msg: - - "Warning! You currently have no nft tables, please review your setup" + - "Warning!! You currently have no nft tables, please review your setup" - 'Use the command "nft create table inet " to create a new table' when: - rhel9cis_3_4_2_5_nft_tables.stdout | length == 0 - not rhel9cis_nft_tables_autonewtable + - name: "3.4.2.5 | AUDIT | Ensure an nftables table exists | Alert on no tables | warning count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_3.4.2.5' ]" + warn_count: "{{ warn_count | int + 1 }}" + when: + - rhel9cis_3_4_2_5_nft_tables.stdout | length == 0 + - not rhel9cis_nft_tables_autonewtable + - name: "3.4.2.5 | PATCH | Ensure a table exists | Create table if needed" command: nft create table inet "{{ rhel9cis_nft_tables_tablename }}" - failed_when: no + failed_when: false when: rhel9cis_nft_tables_autonewtable when: + - rhel9cis_firewall == "nftables" - rhel9cis_rule_3_4_2_5 tags: - level1-server @@ -159,14 +159,15 @@ - name: "3.4.2.6 | PATCH | Ensure nftables base chains exist | Create chains if needed" shell: "{{ item }}" args: - warn: no - failed_when: no + warn: false + failed_when: false with_items: - nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" input { type filter hook input priority 0 \; } - nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" forward { type filter hook forward priority 0 \; } - nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" output { type filter hook output priority 0 \; } when: rhel9cis_nft_tables_autochaincreate when: + - rhel9cis_firewall == "nftables" - rhel9cis_rule_3_4_2_6 tags: - level1-server @@ -208,6 +209,7 @@ command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip6 saddr ::1 counter drop when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in rhel9cis_3_4_2_7_ip6saddr.stdout' when: + - rhel9cis_firewall == "nftables" - rhel9cis_rule_3_4_2_7 tags: - level1-server @@ -255,6 +257,7 @@ command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol icmp ct state new,related,established accept when: '"ip protocol icmp ct state established,related,new accept" not in rhel9cis_3_4_2_8_outconnectionrule.stdout' when: + - rhel9cis_firewall == "nftables" - rhel9cis_rule_3_4_2_8 tags: - level1-server @@ -306,6 +309,7 @@ command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" output { policy drop \; } when: '"type filter hook output priority 0; policy drop;" not in rhel9cis_3_4_2_9_outputpolicy.stdout' when: + - rhel9cis_firewall == "nftables" - rhel9cis_rule_3_4_2_9 tags: - level1-server @@ -318,8 +322,9 @@ - name: "3.4.2.10 | PATCH | Ensure nftables service is enabled" service: name: nftables - enabled: yes + enabled: true when: + - rhel9cis_firewall == "nftables" - rhel9cis_rule_3_4_2_10 tags: - level1-server @@ -332,9 +337,11 @@ - name: "3.4.2.11 | PATCH | Ensure nftables rules are permanent" lineinfile: path: /etc/sysconfig/nftables.conf + state: present insertafter: EOF line: include "/etc/nftables/inet-{{ rhel9cis_nft_tables_tablename }}" when: + - rhel9cis_firewall == "nftables" - rhel9cis_rule_3_4_2_11 tags: - level1-server diff --git a/tasks/section_4/cis_4.1.1.x.yml b/tasks/section_4/cis_4.1.1.x.yml index c78be9b..258b64f 100644 --- a/tasks/section_4/cis_4.1.1.x.yml +++ b/tasks/section_4/cis_4.1.1.x.yml @@ -27,10 +27,9 @@ service: name: auditd state: started - enabled: yes + enabled: true when: - rhel9cis_rule_4_1_1_2 - - ansible_connection != 'docker' tags: - level2-server - level2-workstation @@ -45,7 +44,7 @@ shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//' changed_when: false failed_when: false - check_mode: no + check_mode: false register: rhel9cis_4_1_1_3_grub_cmdline_linux - name: "4.1.1.3 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Replace existing setting" @@ -80,7 +79,7 @@ shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//' changed_when: false failed_when: false - check_mode: no + check_mode: false register: rhel9cis_4_1_1_4_grub_cmdline_linux - name: "4.1.1.4 | PATCH | Ensure audit_backlog_limit is sufficient | Replace existing setting" diff --git a/tasks/section_4/cis_4.1.3.x.yml b/tasks/section_4/cis_4.1.3.x.yml index 0c39267..8272b7e 100644 --- a/tasks/section_4/cis_4.1.3.x.yml +++ b/tasks/section_4/cis_4.1.3.x.yml @@ -1,10 +1,9 @@ --- +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.1 | PATCH | Ensure changes to system administration scope (sudoers) is collected" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_1 tags: @@ -15,11 +14,10 @@ - auditd - rule_4.1.3.1 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.2 | PATCH | Ensure actions as another user are always logged" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_2 tags: @@ -30,11 +28,10 @@ - auditd - rule_4.1.3.2 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.3 | PATCH | Ensure events that modify the sudo log file are collected" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_3 tags: @@ -45,11 +42,10 @@ - auditd - rule_4.1.3.3 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.4 | PATCH | Ensure events that modify date and time information are collected" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_4 tags: @@ -60,11 +56,10 @@ - auditd - rule_4.1.3.4 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.5 | PATCH | Ensure events that modify the system's network environment are collected" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_5 tags: @@ -75,19 +70,19 @@ - auditd - rule_4.1.3.5 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.6 | PATCH | Ensure use of privileged commands is collected" block: - name: "4.1.3.6 | PATCH | Ensure use of privileged commands is collected" shell: for i in $(df | grep '^/dev' | awk '{ print $NF }'); do find $i -xdev -type f -perm -4000 -o -type f -perm -2000 2>/dev/null; done changed_when: false failed_when: false - check_mode: no + check_mode: false register: priv_procs - name: "4.1.3.6 | PATCH | Ensure use of privileged commands is collected" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true + set_fact: + update_audit_template: true notify: update auditd when: - rhel9cis_rule_4_1_3_6 @@ -99,11 +94,10 @@ - auditd - rule_4.1.3.6 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.7 | PATCH | Ensure unsuccessful unauthorized file access attempts are collected" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_7 tags: @@ -114,11 +108,10 @@ - auditd - rule_4.1.3_7 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.8 | PATCH | Ensure events that modify user/group information are collected" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_8 tags: @@ -129,11 +122,10 @@ - auditd - rule_4.1.3.8 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.9 | PATCH | Ensure discretionary access control permission modification events are collected" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_9 tags: @@ -144,11 +136,10 @@ - auditd - rule_4.1.3.9 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.10 | PATCH | Ensure successful file system mounts are collected" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_10 tags: @@ -159,11 +150,10 @@ - auditd - rule_4.1.3.10 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.11 | PATCH | Ensure session initiation information is collected" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_11 tags: @@ -174,11 +164,10 @@ - auditd - rule_4.1.3.11 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.12 | PATCH | Ensure login and logout events are collected" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_12 tags: @@ -189,11 +178,10 @@ - auditd - rule_4.1.3.12 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.13 | PATCH | Ensure file deletion events by users are collected" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_13 tags: @@ -203,11 +191,10 @@ - patch - rule_4.1.3.13 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.14 | PATCH | Ensure events that modify the system's Mandatory Access Controls are collected" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_14 tags: @@ -218,11 +205,10 @@ - auditd - rule_4.1.3.14 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.15 | PATCH | Ensure successful and unsuccessful attempts to use the chcon command are recorded" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_15 tags: @@ -233,11 +219,10 @@ - auditd - rule_4.1.3.15 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.16 | PATCH | Ensure successful and unsuccessful attempts to use the setfacl command are recorded" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_16 tags: @@ -248,11 +233,10 @@ - auditd - rule_4.1.3.16 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.17 | PATCH | Ensure successful and unsuccessful attempts to use the chacl command are recorded" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_17 tags: @@ -263,11 +247,10 @@ - auditd - rule_4.1.3.17 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.18 | PATCH | Ensure successful and unsuccessful attempts to use the usermod command are recorded" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_18 tags: @@ -278,11 +261,10 @@ - auditd - rule_4.1.3.18 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.19 | PATCH | Ensure kernel module loading and unloading is collected" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_19 tags: @@ -293,11 +275,10 @@ - auditd - rule_4.1.3.19 +# All changes selected are managed by the POST audit and handlers to update - name: "4.1.3.20 | PATCH | Ensure the audit configuration is immutable" - debug: - msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules" - changed_when: true - notify: update auditd + set_fact: + update_audit_template: true when: - rhel9cis_rule_4_1_3_20 tags: @@ -321,3 +302,10 @@ - patch - auditd - rule_4.1.3.21 + +- name: Auditd | 4.1.3 | Auditd controls updated + debug: + msg: "Auditd Controls handled in POST using template - updating /etc/auditd/rules.d/99_auditd.rules" + changed_when: false + when: + - update_audit_template diff --git a/tasks/section_4/cis_4.2.1.x.yml b/tasks/section_4/cis_4.2.1.x.yml index 7e70a02..12afac1 100644 --- a/tasks/section_4/cis_4.2.1.x.yml +++ b/tasks/section_4/cis_4.2.1.x.yml @@ -18,7 +18,7 @@ - name: "4.2.1.2 | PATCH | Ensure rsyslog Service is enabled" service: name: rsyslog - enabled: yes + enabled: true when: - rhel9cis_rule_4_2_1_2 tags: @@ -65,10 +65,9 @@ block: - name: "4.2.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out" command: cat /etc/rsyslog.conf - become: yes changed_when: false - failed_when: no - check_mode: no + failed_when: false + check_mode: false register: rhel_08_4_2_1_5_audit - name: "4.2.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out" diff --git a/tasks/section_4/cis_4.2.2.x.yml b/tasks/section_4/cis_4.2.2.x.yml index 9660670..f172f96 100644 --- a/tasks/section_4/cis_4.2.2.x.yml +++ b/tasks/section_4/cis_4.2.2.x.yml @@ -39,8 +39,9 @@ systemd: name: systemd-journal-upload state: started - enabled: yes + enabled: true when: + - rhel9cis_system_is_log_server - rhel9cis_rule_4_2_2_1_3 tags: - level1-server @@ -52,11 +53,12 @@ - name: "4.2.2.1.4 | PATCH | Ensure journald is not configured to recieve logs from a remote client" systemd: - name: systemd-journal-remote + name: systemd-journal-remote.socket state: stopped - enabled: no - masked: yes + enabled: false + masked: true when: + - not rhel9cis_system_is_log_server - rhel9cis_rule_4_2_2_1_4 tags: - level1-server @@ -72,7 +74,7 @@ systemd: name: systemd-journald state: started - enabled: yes + enabled: true - name: "4.2.2.2 | AUDIT | Ensure journald service is enabled | Capture status" shell: systemctl is-enabled systemd-journald.service @@ -83,7 +85,13 @@ - name: "4.2.2.2 | AUDIT | Ensure journald service is enabled | Alert on bad status" debug: msg: - - "Warning! The status of systemd-journald should be static and it is not. Please investigate" + - "Warning!! The status of systemd-journald should be static and it is not. Please investigate" + when: "'static' not in rhel9cis_4_2_2_2_status.stdout" + + - name: "4.2.2.2 | AUDIT | Ensure journald service is enabled | Warn Count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_4.2.2.2' ]" + warn_count: "{{ warn_count | int + 1 }}" when: "'static' not in rhel9cis_4_2_2_2_status.stdout" when: - rhel9cis_rule_4_2_2_2 @@ -134,7 +142,6 @@ notify: restart systemd_journal_upload when: - rhel9cis_rule_4_2_2_5 - - rhel9cis_preferred_log_capture == "journald" tags: - level1-server - level2-workstation @@ -190,9 +197,13 @@ - name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Display file settings" debug: msg: - - "Warning! Below are the current default settings for journald, please confirm they align with your site policies" - # - "{{ rhel9cis_4_2_2_7_override_settings.stdout_lines }}" + - "Warning!! Below are the current default settings for journald, please confirm they align with your site policies" - "{{ (rhel9cis_4_2_2_7_override_status.matched >= 1) | ternary(rhel9cis_4_2_2_7_override_settings.stdout_lines, rhel9cis_4_2_2_7_notoverride_settings.stdout_lines) }}" + + - name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Warn Count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_4.2.2.7' ]" + warn_count: "{{ warn_count | int + 1 }}" when: - rhel9cis_rule_4_2_2_7 tags: diff --git a/tasks/section_4/cis_4.3.yml b/tasks/section_4/cis_4.3.yml index 959fd62..2283d6a 100644 --- a/tasks/section_4/cis_4.3.yml +++ b/tasks/section_4/cis_4.3.yml @@ -16,7 +16,7 @@ - name: "4.3.2 | PATCH | Ensure logrotate is running and enabled" systemd: - name: logrotate + name: logrotate.timer state: started enabled: true when: diff --git a/tasks/section_4/main.yml b/tasks/section_4/main.yml index d28e3ce..6128f16 100644 --- a/tasks/section_4/main.yml +++ b/tasks/section_4/main.yml @@ -17,6 +17,7 @@ - name: "SECTION | 4.2.2 Configure journald" import_tasks: cis_4.2.2.x.yml + when: rhel9cis_syslog == 'journald' - name: "SECTION | 4.2.3 | Configure logile perms" import_tasks: cis_4.2.3.yml diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index 734b434..ef82f98 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -3,7 +3,7 @@ - name: "5.1.1 | PATCH | Ensure cron daemon is enabled" service: name: crond - enabled: yes + enabled: true when: - rhel9cis_rule_5_1_1 tags: diff --git a/tasks/section_5/cis_5.2.x.yml b/tasks/section_5/cis_5.2.x.yml index 7234da6..202ee8c 100644 --- a/tasks/section_5/cis_5.2.x.yml +++ b/tasks/section_5/cis_5.2.x.yml @@ -271,10 +271,21 @@ - rule_5.2.13 - name: "5.2.14 | PATCH | Ensure system-wide crypto policy is not over-ridden" - shell: sed -ri "s/^\s*(CRYPTO_POLICY\s*=.*)$/# \1/" /etc/sysconfig/sshd - args: - warn: no - notify: restart sshd + block: + - name: "5.2.14 | AUDIT | Ensure system-wide crypto policy is not over-ridden" + shell: grep -i '^\s*CRYPTO_POLICY=' /etc/sysconfig/sshd + args: + warn: false + changed_when: false + failed_when: ( ssh_crypto_discovery.rc not in [ 0, 1 ] ) + register: ssh_crypto_discovery + + - name: "5.2.14 | PATCH | Ensure system-wide crypto policy is not over-ridden" + shell: sed -ri "s/^\s*(CRYPTO_POLICY\s*=.*)$/# \1/" /etc/sysconfig/sshd + args: + warn: false + notify: restart sshd + when: ssh_crypto_discovery.stdout | length > 0 when: - rhel9cis_rule_5_2_14 tags: diff --git a/tasks/section_5/cis_5.4.x.yml b/tasks/section_5/cis_5.4.x.yml index 501af41..11ddbbd 100644 --- a/tasks/section_5/cis_5.4.x.yml +++ b/tasks/section_5/cis_5.4.x.yml @@ -6,7 +6,7 @@ shell: 'authselect current | grep "Profile ID: custom/"' failed_when: false changed_when: false - check_mode: no + check_mode: false register: rhel9cis_5_4_1_profiles - name: "5.4.1 | AUDIT | Ensure custom authselect profile is used | Show profiles" @@ -18,7 +18,7 @@ - name: "5.4.1 | PATCH | Ensure custom authselect profile is used | Create custom profiles" shell: authselect create-profile {{ rhel9cis_authselect['custom_profile_name'] }} -b {{ rhel9cis_authselect['default_file_to_copy'] }} args: - warn: no + warn: false when: rhel9cis_authselect_custom_profile_create when: - rhel9cis_rule_5_4_1 @@ -36,7 +36,7 @@ shell: "authselect current | grep with-faillock" failed_when: false changed_when: false - check_mode: no + check_mode: false register: rhel9cis_5_4_2_profiles_faillock - name: "5.4.2 | AUDIT | Ensure authselect includes with-faillock| Show profiles" @@ -48,7 +48,7 @@ - name: "5.4.2 | PATCH | Ensure authselect includes with-faillock | Create custom profiles" shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} with-faillock" args: - warn: no + warn: false when: rhel9cis_authselect_custom_profile_select when: - rhel9cis_rule_5_4_2 diff --git a/tasks/section_5/cis_5.6.1.x.yml b/tasks/section_5/cis_5.6.1.x.yml index c728d90..1163abb 100644 --- a/tasks/section_5/cis_5.6.1.x.yml +++ b/tasks/section_5/cis_5.6.1.x.yml @@ -51,7 +51,7 @@ shell: useradd -D | grep INACTIVE={{ rhel9cis_inactivelock.lock_days }} | cut -f2 -d= changed_when: false failed_when: false - check_mode: no + check_mode: false register: rhel9cis_5_6_1_4_inactive_settings - name: "5.6.1.4 | PATCH | Ensure inactive password lock is 30 days or less | Set default inactive setting" @@ -59,9 +59,9 @@ when: rhel9cis_5_6_1_4_inactive_settings.stdout | length == 0 - name: "5.6.1.4 | AUDIT | Ensure inactive password lock is 30 days or less | Getting user list" - shell: 'egrep ^[^:]+:[^\!*] /etc/shadow | cut -d: -f1' + shell: "awk -F: '/^[^#:]+:[^\\!\\*:]*:[^:]*:[^:]*:[^:]*:[^:]*:(\\s*|-1|3[1-9]|[4-9][0-9]|[1-9][0-9][0-9]+):[^:]*:[^:]*\\s*$/ {print $1}' /etc/shadow" changed_when: false - check_mode: no + check_mode: false register: rhel_8_5_6_1_4_user_list - name: "5.6.1.4 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts" @@ -78,20 +78,20 @@ - password - rule_5.6.1.4 -- name: "5.6.1.5 | PATCH | Ensure all users last password change date is in the past" +- name: "5.6.1.5 | PATCH | Ensure all users last password change date is in the past" block: - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Get current date in Unix Time" shell: echo $(($(date --utc --date "$1" +%s)/86400)) changed_when: false failed_when: false - check_mode: no + check_mode: false register: rhel9cis_5_6_1_5_currentut - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Get list of users with last changed pw date in the future" shell: "cat /etc/shadow | awk -F: '{if($3>{{ rhel9cis_5_6_1_5_currentut.stdout }})print$1}'" changed_when: false failed_when: false - check_mode: no + check_mode: false register: rhel9cis_5_6_1_5_user_list - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Alert no pw change in the future exist" @@ -101,7 +101,15 @@ - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Alert on accounts with pw change in the future" debug: - msg: "Warning! The following accounts have the last PW change date in the future: {{ rhel9cis_5_6_1_5_user_list.stdout_lines }}" + msg: "Warning!! The following accounts have the last PW change date in the future: {{ rhel9cis_5_6_1_5_user_list.stdout_lines }}" + when: + - rhel9cis_5_6_1_5_user_list.stdout | length > 0 + - not rhel9cis_futurepwchgdate_autofix + + - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | warning count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_5.6.1.5' ]" + warn_count: "{{ warn_count | int + 1 }}" when: - rhel9cis_5_6_1_5_user_list.stdout | length > 0 - not rhel9cis_futurepwchgdate_autofix @@ -109,7 +117,7 @@ - name: "5.6.1.5 | PATCH | Ensure all users last password change date is in the past | Fix accounts with pw change in the future" command: passwd --expire {{ item }} when: - - rhel9cis_5_6_1_5_user_list | length > 0 + - rhel9cis_5_6_1_5_user_list.stdout | length > 0 - rhel9cis_futurepwchgdate_autofix with_items: - "{{ rhel9cis_5_6_1_5_user_list.stdout_lines }}" diff --git a/tasks/section_5/cis_5.6.x.yml b/tasks/section_5/cis_5.6.x.yml index 0541f9b..474a378 100644 --- a/tasks/section_5/cis_5.6.x.yml +++ b/tasks/section_5/cis_5.6.x.yml @@ -32,7 +32,7 @@ - item.id != "sync" - item.id != "root" - item.id != "nfsnobody" - - min_int_uid | int < item.gid + - item.gid < min_int_uid | int - item.shell != " /bin/false" - item.shell != " /usr/sbin/nologin" loop_control: @@ -49,7 +49,7 @@ - name: "5.6.3 | PATCH | Ensure default user shell timeout is 900 seconds or less" blockinfile: - create: yes + create: true mode: 0644 dest: "{{ item.dest }}" state: "{{ item.state }}" diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index c169d4b..2cef0f7 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -5,23 +5,31 @@ - name: "6.1.1 | AUDIT | Audit system file permissions | Audit the packages" shell: rpm -Va --nomtime --nosize --nomd5 --nolinkto args: - warn: no + warn: false changed_when: false failed_when: false register: rhel9cis_6_1_1_packages_rpm - name: "6.1.1 | AUDIT | Audit system file permissions | Create list and warning" block: - - name: "6.1.1 | Audit system file permissions | Add file discrepancy list to system" + - name: "6.1.1 | AUDIT | Audit system file permissions | Add file discrepancy list to system" copy: dest: "{{ rhel9cis_rpm_audit_file }}" content: "{{ rhel9cis_6_1_1_packages_rpm.stdout }}" + owner: root + group: root + mode: 0640 - name: "6.1.1 | AUDIT | Audit system file permissions | Message out alert for package descrepancies" debug: msg: | - "Warning! You have some package descrepancies issues. + "Warning!! You have some package descrepancies issues. The file list can be found in {{ rhel9cis_rpm_audit_file }}" + + - name: "6.1.1 | AUDIT | Audit system file permissions | warning count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_6.1.1' ]" + warn_count: "{{ warn_count | int + 1 }}" when: rhel9cis_6_1_1_packages_rpm.stdout|length > 0 - name: "6.1.1 | AUDIT | Audit system file permissions | Message out no package descrepancies" @@ -41,7 +49,7 @@ - name: "6.1.2 | PATCH | Ensure sticky bit is set on all world-writable directories" shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -0002 2>/dev/null | xargs chmod a+t args: - warn: no + warn: false changed_when: false failed_when: false when: diff --git a/tasks/section_6/cis_6.2.x.yml b/tasks/section_6/cis_6.2.x.yml index 31dafa8..eb4bcde 100644 --- a/tasks/section_6/cis_6.2.x.yml +++ b/tasks/section_6/cis_6.2.x.yml @@ -33,8 +33,14 @@ - name: "6.2.2 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Print warning about users with invalid GIDs missing GID entries in /etc/group" debug: - msg: "Warning! The following users have non-existent GIDs (Groups): {{ rhel9cis_6_2_2_passwd_gid_check.stdout_lines | join (', ') }}" - when: rhel9cis_6_2_2_passwd_gid_check.stdout | length > 0 + msg: "Warning!! The following users have non-existent GIDs (Groups): {{ rhel9cis_6_2_2_passwd_gid_check.stdout_lines | join (', ') }}" + when: rhel9cis_6_2_2_passwd_gid_check.stdout | length >= 1 + + - name: "6.2.2 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | warning count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_6.2.2' ]" + warn_count: "{{ warn_count | int + 1 }}" + when: rhel9cis_6_2_2_passwd_gid_check.stdout | length >= 1 when: - rhel9cis_rule_6_2_2 tags: @@ -61,8 +67,14 @@ - name: "6.2.3 | AUDIT| Ensure no duplicate UIDs exist | Print warning about users with duplicate UIDs" debug: - msg: "Warning! The following users have UIDs that are duplicates: {{ rhel9cis_6_2_3_user_uid_check.stdout_lines }}" - when: rhel9cis_6_2_3_user_uid_check.stdout | length > 0 + msg: "Warning!! The following users have UIDs that are duplicates: {{ rhel9cis_6_2_3_user_uid_check.stdout_lines }}" + when: rhel9cis_6_2_3_user_uid_check.stdout | length >= 1 + + - name: "6.2.3 | AUDIT| Ensure no duplicate UIDs exist | warning count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_6.2.3' ]" + warn_count: "{{ warn_count | int + 1 }}" + when: rhel9cis_6_2_3_user_uid_check.stdout | length >= 1 when: - rhel9cis_rule_6_2_3 tags: @@ -89,8 +101,15 @@ - name: "6.2.4 | AUDIT | Ensure no duplicate GIDs exist | Print warning about users with duplicate GIDs" debug: - msg: "Warning! The following groups have duplicate GIDs: {{ rhel9cis_6_2_4_user_user_check.stdout_lines }}" - when: rhel9cis_6_2_4_user_user_check.stdout | length > 0 + msg: "Warning!! The following groups have duplicate GIDs: {{ rhel9cis_6_2_4_user_user_check.stdout_lines }}" + when: rhel9cis_6_2_4_user_user_check.stdout | length >= 1 + + - name: "6.2.4 | AUDIT | Ensure no duplicate GIDs exist | warning count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_6.2.4' ]" + warn_count: "{{ warn_count | int + 1 }}" + when: rhel9cis_6_2_4_user_user_check.stdout | length >= 1 + when: - rhel9cis_rule_6_2_4 tags: @@ -117,8 +136,14 @@ - name: "6.2.5 | AUDIT | Ensure no duplicate user names exist | Print warning about users with duplicate User Names" debug: - msg: "Warning! The following user names are duplicates: {{ rhel9cis_6_2_5_user_username_check.stdout_lines }}" - when: rhel9cis_6_2_5_user_username_check.stdout | length > 0 + msg: "Warning!! The following user names are duplicates: {{ rhel9cis_6_2_5_user_username_check.stdout_lines }}" + when: rhel9cis_6_2_5_user_username_check.stdout | length >= 1 + + - name: "6.2.5 | AUDIT | Ensure no duplicate user names exist | warning count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_6.2.5' ]" + warn_count: "{{ warn_count | int + 1 }}" + when: rhel9cis_6_2_5_user_username_check.stdout | length >= 1 when: - rhel9cis_rule_6_2_5 tags: @@ -136,18 +161,24 @@ shell: 'getent passwd | cut -d: -f1 | sort -n | uniq -d' changed_when: false failed_when: false - check_mode: no + check_mode: false register: rhel9cis_6_2_6_group_group_check - name: "6.2.6 | AUDIT | Ensure no duplicate group names exist | Print message that no duplicate groups exist" debug: msg: "Good News! There are no duplicate group names in the system" - when: rhel9cis_6_2_6_group_group_check.stdout | length == 0 + when: rhel9cis_6_2_6_group_group_check.stdout is defined - name: "6.2.6 | AUDIT | Ensure no duplicate group names exist | Print warning about users with duplicate group names" debug: - msg: "Warning! The following group names are duplicates: {{ rhel9cis_6_2_6_group_group_check.stdout_lines }}" - when: rhel9cis_6_2_6_group_group_check.stdout | length > 0 + msg: "Warning!! The following group names are duplicates: {{ rhel9cis_6_2_6_group_group_check.stdout_lines }}" + when: rhel9cis_6_2_6_group_group_check.stdout is not defined + + - name: "6.2.6 | AUDIT | Ensure no duplicate group names exist | warning count" + set_fact: + control_number: "{{ control_number }} + [ 'rule_6.2.6' ]" + warn_count: "{{ warn_count | int + 1 }}" + when: rhel9cis_6_2_6_group_group_check.stdout is not defined when: - rhel9cis_rule_6_2_6 tags: @@ -163,23 +194,23 @@ block: - name: "6.2.7 | AUDIT | Ensure root PATH Integrity | Determine empty value" shell: 'echo $PATH | grep ::' - changed_when: False + changed_when: false failed_when: rhel9cis_6_2_7_path_colon.rc == 0 - check_mode: no + check_mode: false register: rhel9cis_6_2_7_path_colon - name: "6.2.7 | AUDIT | Ensure root PATH Integrity | Determin colon end" shell: 'echo $PATH | grep :$' - changed_when: False + changed_when: false failed_when: rhel9cis_6_2_7_path_colon_end.rc == 0 - check_mode: no + check_mode: false register: rhel9cis_6_2_7_path_colon_end - name: "6.2.7 | AUDIT | Ensure root PATH Integrity | Determine dot in path" shell: "/bin/bash --login -c 'env | grep ^PATH=' | sed -e 's/PATH=//' -e 's/::/:/' -e 's/:$//' -e 's/:/\\n/g'" - changed_when: False + changed_when: false failed_when: '"." in rhel9cis_6_2_7_dot_in_path.stdout_lines' - check_mode: no + check_mode: false register: rhel9cis_6_2_7_dot_in_path - name: "6.2.7 | AUDIT | Ensure root PATH Integrity | Alert on empty value, colon end, and dot in path" @@ -230,7 +261,7 @@ stat: path: "{{ item }}" register: rhel_08_6_2_9_audit - with_items: "{{ rhel9cis_passwd | selectattr('uid', '>=', min_int_uid | int ) | selectattr('uid', '<', max_int_uid | int ) | map(attribute='dir') | list }}" + with_items: "{{ rhel9cis_passwd | selectattr('uid', '>=', min_int_uid | int ) | selectattr('uid', '<=', max_int_uid | int ) | map(attribute='dir') | list }}" - name: "6.2.9 | AUDIT | Ensure all users' home directories exist" command: find -H {{ item.0 | quote }} -not -type l -perm /027 @@ -249,7 +280,7 @@ - name: "6.2.9 | PATCH | Ensure all users' home directories exist" file: path: "{{ item.0 }}" - recurse: yes + recurse: true mode: a-st,g-w,o-rwx register: rhel_08_6_2_9_patch when: @@ -265,12 +296,13 @@ - name: "6.2.9 | PATCH | Ensure all users' home directories exist" acl: path: "{{ item.0 }}" - default: yes + default: true state: present - recursive: yes + recursive: true etype: "{{ item.1.etype }}" permissions: "{{ item.1.mode }}" - when: not system_is_container + when: + - not system_is_container with_nested: - "{{ (ansible_check_mode | ternary(rhel_08_6_2_9_patch_audit, rhel_08_6_2_9_patch)).results | rejectattr('skipped', 'defined') | map(attribute='item') | map('first') | list }}" @@ -299,7 +331,8 @@ loop_control: label: "{{ rhel9cis_passwd_label }}" when: - - min_int_uid | int <= item.uid + - item.uid >= min_int_uid | int + - item.id != 'nobody' - rhel9cis_rule_6_2_10 tags: - skip_ansible_lint # settings found on 6_2_7 @@ -315,7 +348,7 @@ - name: "6.2.11 | AUDIT | Ensure users' home directories permissions are 750 or more restrictive" stat: path: "{{ item }}" - with_items: "{{ rhel9cis_passwd | selectattr('uid', '>=', min_int_uid | int ) | selectattr('uid', '<', max_int_uid | int ) | map(attribute='dir') | list }}" + with_items: "{{ rhel9cis_passwd | selectattr('uid', '>=', min_int_uid | int) | selectattr('uid', '<=', max_int_uid | int) | map(attribute='dir') | list }}" register: rhel_08_6_2_11_audit - name: "6.2.11 | AUDIT | Ensure users' home directories permissions are 750 or more restrictive" @@ -335,7 +368,7 @@ - name: "6.2.11 | PATCH | Ensure users' home directories permissions are 750 or more restrictive" file: path: "{{ item.0 }}" - recurse: yes + recurse: true mode: a-st,g-w,o-rwx register: rhel_08_6_2_11_patch when: @@ -351,12 +384,13 @@ - name: "6.2.11 | PATCH | Ensure users' home directories permissions are 750 or more restrictive" acl: path: "{{ item.0 }}" - default: yes + default: true state: present - recursive: yes + recursive: true etype: "{{ item.1.etype }}" permissions: "{{ item.1.mode }}" - when: not system_is_container + when: + - not system_is_container with_nested: - "{{ (ansible_check_mode | ternary(rhel_08_6_2_11_patch_audit, rhel_08_6_2_11_patch)).results | rejectattr('skipped', 'defined') | map(attribute='item') | map('first') | list }}" @@ -427,8 +461,8 @@ - name: "6.2.14 | PATCH | Ensure no users have .forward files" file: + path: "~{{ item }}/.forward" state: absent - dest: "~{{ item }}/.forward" with_items: - "{{ users.stdout_lines }}" when: @@ -444,8 +478,8 @@ - name: "6.2.15 | PATCH | Ensure no users have .netrc files" file: + path: "~{{ item }}/.netrc" state: absent - dest: "~{{ item }}/.netrc" with_items: - "{{ users.stdout_lines }}" when: @@ -461,8 +495,8 @@ - name: "6.2.16 | PATCH | Ensure no users have .rhosts files" file: + path: "~{{ item }}/.rhosts" state: absent - dest: "~{{ item }}/.rhosts" with_items: "{{ users.stdout_lines }}" when: - rhel9cis_rule_6_2_16 diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index 6654add..1431ed4 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -1,3 +1,5 @@ + +## This file is managed by Ansible, YOUR CHANGED WILL BE LOST! ## metadata for benchmark ## metadata for Audit benchmark @@ -157,6 +159,7 @@ rhel9cis_rule_2_3_2: {{ rhel9cis_rule_2_3_2 }} rhel9cis_rule_2_3_3: {{ rhel9cis_rule_2_3_3 }} rhel9cis_rule_2_3_4: {{ rhel9cis_rule_2_3_4 }} rhel9cis_rule_2_3_5: {{ rhel9cis_rule_2_3_5 }} +rhel9cis_rule_2_3_6: {{ rhel9cis_rule_2_3_6 }} rhel9cis_rule_2_4: true # todo @@ -274,6 +277,7 @@ rhel9cis_rule_5_1_5: {{ rhel9cis_rule_5_1_5 }} rhel9cis_rule_5_1_6: {{ rhel9cis_rule_5_1_6 }} rhel9cis_rule_5_1_7: {{ rhel9cis_rule_5_1_7 }} rhel9cis_rule_5_1_8: {{ rhel9cis_rule_5_1_8 }} +rhel9cis_rule_5_1_9: {{ rhel9cis_rule_5_1_9 }} # 5.2 Configure SSH Server rhel9cis_rule_5_2_1: {{ rhel9cis_rule_5_2_1 }} @@ -492,4 +496,4 @@ rhel9cis_pass: rhel9cis_sugroup: {% if rhel9cis_sugroup is undefined %}wheel{% else %}{{ rhel9cis_sugroup }}{% endif %} ## 5.3.7 sugroup users list -rhel9cis_sugroup_users: {{ rhel9cis_sugroup_users }} \ No newline at end of file +rhel9cis_sugroup_users: {{ rhel9cis_sugroup_users }} diff --git a/templates/audit/98_auditd_exception.rules.j2 b/templates/audit/98_auditd_exception.rules.j2 new file mode 100644 index 0000000..d8a0b8d --- /dev/null +++ b/templates/audit/98_auditd_exception.rules.j2 @@ -0,0 +1,8 @@ +## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! + +# This file contains users whose actions are not logged by auditd +{% if allow_auditd_uid_user_exclusions %} +{% for user in rhel9cis_auditd_uid_exclude %} +-a never,user -F uid!={{ user }} -F auid!={{ user }} +{% endfor %} +{% endif %} diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 7abe895..050de20 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -1,3 +1,5 @@ +## This file is managed by Ansible, 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 {% if rhel9cis_rule_4_1_3_1 %} -w /etc/sudoers -p wa -k scope diff --git a/templates/etc/chrony.conf.j2 b/templates/etc/chrony.conf.j2 index 6513faa..54c1b6c 100644 --- a/templates/etc/chrony.conf.j2 +++ b/templates/etc/chrony.conf.j2 @@ -1,3 +1,5 @@ +## This file is managed by Ansible, YOUR CHANGED WILL BE LOST! + # This the default chrony.conf file for the Debian chrony package. After # editing this file use the command 'invoke-rc.d chrony restart' to make # your changes take effect. John Hasler 1998-2008 diff --git a/templates/etc/cron.d/aide.cron.j2 b/templates/etc/cron.d/aide.cron.j2 index f9014fa..781fdd4 100644 --- a/templates/etc/cron.d/aide.cron.j2 +++ b/templates/etc/cron.d/aide.cron.j2 @@ -1,5 +1,5 @@ # Run AIDE integrity check -# added via ansible-lockdown remediation +## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! # CIS 1.3.2 {{ rhel9cis_aide_cron['aide_minute'] }} {{ rhel9cis_aide_cron['aide_hour'] }} {{ rhel9cis_aide_cron['aide_month'] }} {{ rhel9cis_aide_cron['aide_weekday'] }} {{ rhel9cis_aide_cron['aide_job'] }} diff --git a/templates/etc/modprobe.d/modprobe.conf.j2 b/templates/etc/modprobe.d/modprobe.conf.j2 index 1a1a48d..77b8cd5 100644 --- a/templates/etc/modprobe.d/modprobe.conf.j2 +++ b/templates/etc/modprobe.d/modprobe.conf.j2 @@ -1,5 +1,6 @@ # Disable usage of protocol {{ item }} # Set by ansible {{ benchmark }} remediation role # https://github.com/ansible-lockdown +## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! -install {{ item }} /bin/true \ No newline at end of file +install {{ item }} /bin/true diff --git a/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 b/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 index 34ee10c..732cbcc 100644 --- a/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 +++ b/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 @@ -1,4 +1,4 @@ -# Setting added via ansible CIS remediation playbook +## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! # IPv6 disable {% if rhel9cis_rule_3_1_1 and rhel9cis_ipv6_required %} diff --git a/templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 b/templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 index cbfffed..8bd0157 100644 --- a/templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 +++ b/templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 @@ -1,4 +1,4 @@ -# Setting added via ansible CIS remediation playbook +## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! {% if rhel9cis_rule_1_5_3 %} diff --git a/templates/etc/sysctl.d/60-netipv4_sysctl.conf.j2 b/templates/etc/sysctl.d/60-netipv4_sysctl.conf.j2 index 308b914..8bafbf9 100644 --- a/templates/etc/sysctl.d/60-netipv4_sysctl.conf.j2 +++ b/templates/etc/sysctl.d/60-netipv4_sysctl.conf.j2 @@ -1,4 +1,4 @@ -# Setting added via ansible CIS remediation playbook +## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! # IPv4 Network sysctl {% if rhel9cis_rule_3_2_1 %} diff --git a/templates/etc/sysctl.d/60-netipv6_sysctl.conf.j2 b/templates/etc/sysctl.d/60-netipv6_sysctl.conf.j2 index 0b23c55..e85fae9 100644 --- a/templates/etc/sysctl.d/60-netipv6_sysctl.conf.j2 +++ b/templates/etc/sysctl.d/60-netipv6_sysctl.conf.j2 @@ -1,4 +1,4 @@ -# Setting added via ansible CIS remediation playbook +## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! # IPv6 Network sysctl {% if rhel9cis_ipv6_required %} diff --git a/templates/etc/systemd/system/tmp.mount.j2 b/templates/etc/systemd/system/tmp.mount.j2 index 2a97a56..f2c4fe2 100644 --- a/templates/etc/systemd/system/tmp.mount.j2 +++ b/templates/etc/systemd/system/tmp.mount.j2 @@ -7,6 +7,8 @@ # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. +## This file is managed by Ansible, YOUR CHANGED WILL BE LOST! + [Unit] Description=Temporary Directory (/tmp) Documentation=man:hier(7) diff --git a/vars/AlmaLinux.yml b/vars/AlmaLinux.yml index 69e5994..c460fb0 100644 --- a/vars/AlmaLinux.yml +++ b/vars/AlmaLinux.yml @@ -1,4 +1,5 @@ --- # OS Specific Settings -rpm_gpg_key: RPM-GPG-KEY-AlmaLinux +os_gpg_key_pubkey_name: gpg-pubkey-b86b3716-61e69f29 +os_gpg_key_pubkey_content: "AlmaLinux OS 9 b86b3716" diff --git a/vars/RedHat.yml b/vars/RedHat.yml index 0b1c2cc..d33b0bc 100644 --- a/vars/RedHat.yml +++ b/vars/RedHat.yml @@ -1,6 +1,5 @@ --- # OS Specific Settings -rpm_gpg_key: /etc/pki/rpm-gpg/RPM-GPG-KEY-{{ ansible_distribution|lower }}-release -rpm_packager: "Red Hat, Inc" -rpm_key: "199e2f91fd431d51" # found on https://access.redhat.com/security/team/key/ +os_gpg_key_pubkey_name: gpg-pubkey-fd431d51-4ae0493b +os_gpg_key_pubkey_content: "Red Hat, Inc. (release key 2) fd431d51" diff --git a/vars/Rocky.yml b/vars/Rocky.yml index 7c8ae0b..77af29c 100644 --- a/vars/Rocky.yml +++ b/vars/Rocky.yml @@ -1,4 +1,5 @@ --- # OS Specific Settings -rpm_gpg_key: /etc/pki/rpm-gpg/RPM-GPG-KEY-rockyofficial +os_gpg_key_pubkey_name: gpg-pubkey-350d275d-6279464b +os_gpg_key_pubkey_content: "Rocky Enterprise Software Foundation - Release key 2022 350d275d" diff --git a/vars/main.yml b/vars/main.yml index dbbc71f..2ba64a1 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -1,8 +1,12 @@ --- # vars file for RHEL9-CIS -min_ansible_version: 2.10 +min_ansible_version: 2.9.4 rhel9cis_allowed_crypto_policies: - 'DEFAULT' - 'FUTURE' - 'FIPS' + +# Used to control warning summary +control_number: "" +warn_count: 0