From 3c7ab9f68790c55d511eb53384993d6630c72755 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 7 Feb 2025 12:24:35 +0000 Subject: [PATCH 001/116] updated logic in 7.2.9 Signed-off-by: Mark Bolwell --- tasks/section_7/cis_7.2.x.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml index 2a33f33..cc1825c 100644 --- a/tasks/section_7/cis_7.2.x.yml +++ b/tasks/section_7/cis_7.2.x.yml @@ -287,15 +287,15 @@ warn_control_id: '7.2.9' block: - name: "7.2.9 | AUDIT | Ensure local interactive user dot files access is configured | Check for files" - ansible.builtin.shell: find /home/ -name "\.*" -perm /g+w,o+w + ansible.builtin.shell: find /home/ -name "\.*" changed_when: false - failed_when: discovered_homedir_dot_files.rc not in [ 0, 1 ] + failed_when: discovered_homedir_hidden_files.rc not in [ 0, 1 ] check_mode: false - register: discovered_homedir_dot_files + register: discovered_homedir_hidden_files - name: "7.2.9 | AUDIT | Ensure local interactive user dot files access is configured | Warning on files found" when: - - discovered_homedir_dot_files.stdout | length > 0 + - discovered_homedir_hidden_files.stdout | length > 0 - rhel9cis_dotperm_ansiblemanaged ansible.builtin.debug: msg: @@ -303,16 +303,18 @@ - name: "7.2.9 | PATCH | Ensure local interactive user dot files access is configured | Set warning count" when: - - discovered_homedir_dot_files.stdout | length > 0 + - discovered_homedir_hidden_files.stdout | length > 0 - rhel9cis_dotperm_ansiblemanaged ansible.builtin.import_tasks: file: warning_facts.yml - name: "7.2.9 | PATCH | Ensure local interactive user dot files access is configured | Changes files if configured" when: - - discovered_homedir_dot_files.stdout | length > 0 + - discovered_homedir_hidden_files.stdout | length > 0 - rhel9cis_dotperm_ansiblemanaged ansible.builtin.file: path: '{{ item }}' mode: 'go-w' - with_items: "{{ discovered_homedir_dot_files.stdout_lines }}" + owner: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" + group: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" + with_items: "{{ discovered_homedir_hidden_files.stdout_lines }}" From 7a3efd492078a203767e80db4ec2d7f14f125646 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 1 Apr 2025 09:51:53 +0100 Subject: [PATCH 002/116] added fetch and ansible facts Signed-off-by: Mark Bolwell --- defaults/main.yml | 17 +++++++++ tasks/fetch_audit_output.yml | 46 +++++++++++++++++++++++ tasks/main.yml | 30 +++++++++++++++ templates/etc/ansible/compliance_facts.j2 | 39 +++++++++++++++++++ 4 files changed, 132 insertions(+) create mode 100644 tasks/fetch_audit_output.yml create mode 100644 templates/etc/ansible/compliance_facts.j2 diff --git a/defaults/main.yml b/defaults/main.yml index da5ca20..32c4679 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -33,6 +33,9 @@ rhel9cis_section7: true rhel9cis_level_1: true rhel9cis_level_2: true +# Create managed not custom local_facts files +create_benchmark_facts: true +ansible_facts_path: /etc/ansible/facts.d ## Section 1.6 - Mandatory Access Control # This variable governs whether SELinux is disabled or not. If SELinux is NOT DISABLED by setting # 'rhel9cis_selinux_disable' to 'true', the 1.6 subsection will be executed. @@ -107,6 +110,20 @@ audit_conf_dest: "/opt" # Where the audit logs are stored audit_log_dir: '/opt' +## Ability to collect and take audit files moving to a centralised location +# This enables the collection of the files from the host +fetch_audit_output: false + +# Method of getting,uploading the summary files +## Ensure access and permissions are avaiable for these to occur. +## options are +# fetch - fetches from server and moves to location on the ansible controller (could be a mount point available to controller) +# copy - copies file to a location available to the managed node +audit_output_collection_method: fetch + +# Location to put the audit files +audit_output_destination: /opt/audit_summaries/ + ### Goss Settings ## ####### END ######## diff --git a/tasks/fetch_audit_output.yml b/tasks/fetch_audit_output.yml new file mode 100644 index 0000000..c6f7b5e --- /dev/null +++ b/tasks/fetch_audit_output.yml @@ -0,0 +1,46 @@ +--- + +# Stage to copy audit output to a centralised location + +- name: "FETCH_AUDIT_FILES | Fetch files and copy to controller" + when: audit_output_collection_method == "fetch" + ansible.builtin.fetch: + src: "{{ item }}" + dest: "{{ audit_output_destination }}" + flat: true + failed_when: false + register: discovered_audit_fetch_state + loop: + - "{{ pre_audit_outfile }}" + - "{{ post_audit_outfile }}" + become: false + +# Added this option for continuity but could be changed by adjusting the variable audit_conf_dest +# Allowing backup to one location +- name: "FETCH_AUDIT_FILES | Copy files to location available to managed node" + when: audit_output_collection_method == "copy" + ansible.builtin.copy: + src: "{{ item }}" + dest: "{{ audit_output_destination }}" + mode: 'u-x,go-wx' + flat: true + failed_when: false + register: discovered_audit_fetch_copy_state + loop: + - pre_audit_outfile + - post_audit_outfile + +- name: "FETCH_AUDIT_FILES | Fetch files and copy to controller | Warning if issues with fetch_audit_files" + when: + - (discovered_audit_fetch_state is defined and not discovered_audit_fetch_state.changed) or + (discovered_audit_copy_state is defined and not discovered_audit_copy_state.changed) + block: + - name: "FETCH_AUDIT_FILES | Fetch files and copy to controller | Warning if issues with fetch_audit_files" + ansible.builtin.debug: + msg: "Warning!! Unable to write to localhost {{ audit_output_destination }} for audit file copy" + + - name: "FETCH_AUDIT_FILES | Fetch files and copy to controller | Warning if issues with fetch_audit_files" + vars: + warn_control_id: "FETCH_AUDIT_FILES" + ansible.builtin.import_tasks: + file: warning_facts.yml diff --git a/tasks/main.yml b/tasks/main.yml index a0a58f8..7bccabf 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -212,6 +212,36 @@ ansible.builtin.import_tasks: file: post_remediation_audit.yml +- name: Add ansible file showing Benchmark and levels applied + when: create_benchmark_facts + tags: + - always + - benchmark + block: + - name: Create ansible facts directory + ansible.builtin.file: + path: "{{ ansible_facts_path }}" + state: directory + owner: root + group: root + mode: 'u=rwx,go=rx' + + - name: Create ansible facts file + ansible.builtin.template: + src: etc/ansible/compliance_facts.j2 + dest: "{{ ansible_facts_path }}/compliance_facts.fact" + owner: root + group: root + mode: "u-x,go-wx" + +- name: Fetch audit files + when: + - fetch_audit_output + - run_audit + tags: always + ansible.builtin.import_tasks: + file: fetch_audit_output.yml + - name: "Show Audit Summary" when: run_audit ansible.builtin.debug: diff --git a/templates/etc/ansible/compliance_facts.j2 b/templates/etc/ansible/compliance_facts.j2 new file mode 100644 index 0000000..f313bec --- /dev/null +++ b/templates/etc/ansible/compliance_facts.j2 @@ -0,0 +1,39 @@ +# CIS Hardening Carried out +# Added as part of ansible-lockdown CIS baseline +# provided by Mindpoint Group - A Tyto Athene Company + +[lockdown_details] +# Benchmark release +Benchmark_release = CIS-{{ benchmark_version }} +Benchmark_run_date = {{ '%Y-%m-%d - %H:%M:%S' | ansible.builtin.strftime }} +# If options set (doesn't mean it ran all controls) +level_1_hardening_enabled = {{ rhel9cis_level_1 }} +level_2_hardening_enabled = {{ rhel9cis_level_2 }} + +{% if ansible_run_tags | length > 0 %} +# If tags used to stipulate run level +{% if 'level1-server' in ansible_run_tags %} +Level_1_Server_tag_run = true +{% endif %} +{% if 'level2-server' in ansible_run_tags %} +Level_2_Server_tag_run = true +{% endif %} +{% if 'level1-workstation' in ansible_run_tags %} +Level_1_workstation_tag_run = true +{% endif %} +{% if 'level2-workstation' in ansible_run_tags %} +Level_2_workstation_tag_run = true +{% endif %} +{% endif %} + +[lockdown_audit_details] +{% if run_audit %} +# Audit run +audit_file_local_location = {{ audit_log_dir }} +{% if not audit_only %} +audit_summary = {{ post_audit_results }} +{% endif %} +{% if fetch_audit_output %} +audit_files_centralized_location = {{ audit_output_destination }} +{% endif %} +{% endif %} From 37868f591b6a67ad8661c07c75ac9f8e953fe20d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 1 Apr 2025 09:53:29 +0100 Subject: [PATCH 003/116] updated workflows Signed-off-by: Mark Bolwell --- .github/workflows/devel_pipeline_validation.yml | 1 + .github/workflows/main_pipeline_validation.yml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index c9328cb..10750a2 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -7,6 +7,7 @@ types: [opened, reopened, synchronize] branches: - devel + - benchmark* paths: - '**.yml' - '**.sh' diff --git a/.github/workflows/main_pipeline_validation.yml b/.github/workflows/main_pipeline_validation.yml index ab11c37..6792a00 100644 --- a/.github/workflows/main_pipeline_validation.yml +++ b/.github/workflows/main_pipeline_validation.yml @@ -7,6 +7,7 @@ types: [opened, reopened, synchronize] branches: - main + - latest paths: - '**.yml' - '**.sh' @@ -23,6 +24,7 @@ # A workflow run is made up of one or more jobs # that can run sequentially or in parallel jobs: + # This workflow contains a single job that tests the playbook playbook-test: # The type of runner that the job will run on From 9e40054489d82f4723bab7bf6b5942a00d7e1a5d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 1 Apr 2025 09:55:06 +0100 Subject: [PATCH 004/116] updated Signed-off-by: Mark Bolwell --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4791982..cf62311 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -65,7 +65,7 @@ repos: # - ansible-core>=2.10.1 - repo: https://github.com/adrienverge/yamllint.git - rev: v1.35.1 # or higher tag + rev: v1.37.0 # or higher tag hooks: - id: yamllint name: Check YAML Lint From a41de702f42cf62009468b0ede1e096b2a5860ed Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 1 Apr 2025 10:00:24 +0100 Subject: [PATCH 005/116] lint updates Signed-off-by: Mark Bolwell --- .pre-commit-config.yaml | 4 +++- tasks/main.yml | 2 +- tasks/section_1/cis_1.4.x.yml | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cf62311..ceb4475 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,11 +39,13 @@ repos: rev: v1.5.0 hooks: - id: detect-secrets + name: Detect Secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.24.0 + rev: v8.24.2 hooks: - id: gitleaks + name: GitLeaks - repo: https://github.com/ansible-community/ansible-lint rev: v25.1.3 diff --git a/tasks/main.yml b/tasks/main.yml index 7bccabf..3468075 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -116,7 +116,7 @@ fail_msg: "You still have the default name for your authselect profile" - name: "Check authselect profile is selected | Check current profile" - ansible.builtin.shell: authselect list + ansible.builtin.command: authselect list changed_when: false failed_when: prelim_authselect_current_profile.rc not in [ 0, 1 ] register: prelim_authselect_current_profile diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index d3534cd..c6c3aac 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -57,7 +57,7 @@ - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | efi based system | Build Options" when: item not in discovered_efi_fstab.stdout ansible.builtin.set_fact: - efi_mount_opts_addition: "{{ efi_mount_opts_addition + ',' + item }}" + efi_mount_opts_addition: "{{ efi_mount_opts_addition + ',' + item }}" loop: "{{ efi_mount_options }}" - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | efi based system | Add mount options" From 120207440ccbbebb8a8cd037e290a9b8099dc254 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Tue, 15 Apr 2025 15:22:19 -0400 Subject: [PATCH 006/116] Typo fixes Signed-off-by: Frederick Witty --- README.md | 2 +- defaults/main.yml | 22 +++++++++++----------- tasks/post_remediation_audit.yml | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 745039d..6601ebf 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ This is managed using tags: - level2-server - level2-workstation -The control found in defaults main also need to reflect this as this control the testing thet takes place if you are using the audit component. +The control found in defaults main also need to reflect this as this control the testing that takes place if you are using the audit component. ## Coming from a previous release diff --git a/defaults/main.yml b/defaults/main.yml index 3f6202b..6482654 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,7 +1,7 @@ --- # defaults file for rhel9-cis # WARNING: -# These values may be overriden by other vars-setting options(e.g. like the below 'container_vars_file'), as explained here: +# These values may be overridden by other vars-setting options(e.g. like the below 'container_vars_file'), as explained here: # https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable # Run the OS validation check @@ -41,7 +41,7 @@ rhel9cis_selinux_disable: false # UEFI boot('/etc/grub2-efi.cfg') or in case of BIOS legacy-boot('/etc/grub2.cfg'). rhel9cis_legacy_boot: false -## Benchmark name used by audting control role +## Benchmark name used by auditing control role # The audit variable found at the base ## metadata for Audit benchmark benchmark_version: 'v2.0.0' @@ -82,7 +82,7 @@ audit_capture_files_dir: /some/location to copy to on control node # How to retrieve audit binary # Options are copy or download - detailed settings at the bottom of this file -# you will need to access to either github or the file already dowmloaded +# you will need to access to either github or the file already downloaded get_audit_binary_method: download ## if get_audit_binary_method - copy the following needs to be updated for your environment @@ -97,7 +97,7 @@ audit_content: git # If using either archive, copy, get_url: ## Note will work with .tar files - zip will require extra configuration ### If using get_url this is expecting github url in tar.gz format e.g. -### https://github.com/ansible-lockdown/UBUNTU22-CIS-Audit/archive/refs/heads/benchmark-v1.0.0.tar.gz +### https://github.com/ansible-lockdown/RHEL9-CIS-Audit/archive/refs/heads/benchmark-v1.0.0.tar.gz audit_conf_source: "some path or url to copy from" # Destination for the audit content to be placed on managed node @@ -220,7 +220,7 @@ rhel9cis_rule_1_8_8: true rhel9cis_rule_1_8_9: true rhel9cis_rule_1_8_10: true -# Section 2 rules are controling Services (Special Purpose Services, and service clients) +# Section 2 rules are controlling Services (Special Purpose Services, and service clients) ## Configure Server Services rhel9cis_rule_2_1_1: true rhel9cis_rule_2_1_2: true @@ -703,7 +703,7 @@ rhel9cis_bluetooth_mask: false rhel9cis_ipv6_required: true ## 3.1.2 wireless network requirements -# if wireless adapetr found allow network manager to be installed +# if wireless adapter found allow network manager to be installed rhel9cis_install_network_manager: false # 3.3 System network parameters (host only OR host and router) # This variable governs whether specific CIS rules @@ -711,15 +711,15 @@ rhel9cis_install_network_manager: false rhel9cis_is_router: false # This variable governs if the task which updates sysctl(including sysctl reload) is executed. -# NOTE: The current default value is likely to be overriden by other further tasks(via 'set_fact'). +# NOTE: The current default value is likely to be overridden by other further tasks(via 'set_fact'). rhel9cis_sysctl_update: false # This variable governs if the task which flushes the IPv4 routing table is executed(forcing subsequent connections to # use the new configuration). -# NOTE: The current default value is likely to be overriden by other further tasks(via 'set_fact'). +# NOTE: The current default value is likely to be overridden by other further tasks(via 'set_fact'). rhel9cis_flush_ipv4_route: false # This variable governs if the task which flushes the IPv6 routing table is executed(forcing subsequent connections to # use the new configuration). -# NOTE: The current default value is likely to be overriden by other further tasks(via 'set_fact'). +# NOTE: The current default value is likely to be overridden by other further tasks(via 'set_fact'). rhel9cis_flush_ipv6_route: false # Section 4 vars @@ -871,13 +871,13 @@ rhel9cis_authselect_pkg_update: false # NOTE the risks if system is using SSSD # To create a new profile (best for greenfield fresh sites not configured) # This allows creation of a custom profile using an existing one to build from -# will only create if profiel does not already exist +# will only create if profile does not already exist ## options true or false rhel9cis_authselect_custom_profile_create: true ## Controls: # - 5.3.2.1 - Ensure custom authselect profile is used # Settings in place now will fail, they are placeholders from the control example. Due to the way many multiple -# options and ways to configure this control needs to be enabled and settings adjusted to minimise risk. +# options and ways to configure this control needs to be enabled and settings adjusted to minimize risk. # This variable configures the name of the custom profile to be created and selected. # To be changed from default - cis_example_profile diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 54d5785..68e7035 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -33,7 +33,7 @@ when: audit_format == "documentation" block: - name: Post Audit | Capture audit data if documentation format - ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' + ansible.builtin.shell: tail -2 "{{ post_audit_outfile }}" | tac | tr '\n' ' ' changed_when: false register: post_audit_summary From 23b29090735b1f06cc12015dc2288f731e25af45 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Thu, 15 May 2025 16:48:44 -0400 Subject: [PATCH 007/116] QA Fixes Signed-off-by: Frederick Witty --- Changelog.md | 19 ++++++++++++------- defaults/main.yml | 4 ++-- tasks/LE_audit_setup.yml | 1 + tasks/audit_only.yml | 1 + tasks/main.yml | 4 +--- tasks/post.yml | 3 +-- tasks/prelim.yml | 2 +- vars/is_container.yml | 2 +- 8 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Changelog.md b/Changelog.md index 4bd1c86..d9aa825 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,10 @@ # Changes to rhel9CIS +## 2.0.0 - Based on CIS v2.0.0 + +- May 2025 QA Fixes + - Typo fixes and Banner verbiage + ## 1.1.6 - Based on CIS v1.0.0 - #190 - thanks to @ipruteanu-sie @@ -14,7 +19,7 @@ - updated controls 6.2.10-6.2.14 - audit - steps moved to prelim - - update to coipy and archive logic and variables + - update to copy and archive logic and variables - removed vars not used - updated quotes used in mode tasks - pre-commit update @@ -48,7 +53,7 @@ - lint updates - .secrets updated - file mode quoted -- updated 5.6.5 thansk to feedback from S!ghs on discord community +- updated 5.6.5 thanks to feedback from S!ghs on discord community ## 1.1.1 - Based on CIS v1.0.0 @@ -80,7 +85,7 @@ ## 1.0.10 - [#72](https://github.com/ansible-lockdown/RHEL9-CIS/issues/72) - - Only run check when paybook user not a superuser + - Only run check when playbook user not a superuser - fix for 5.5.3 thanks to @nrg-fv ## 1.0.9 @@ -152,7 +157,7 @@ Jan-2023 release - updated ansible minimum to 2.10 - Lint file updates and improvements -- auditd now shows diff ater initial template added +- auditd now shows diff after initial template added - many control rewritten - Many controls moved ID references - Audit updates aligned @@ -217,11 +222,11 @@ Jan-2023 release - not all controls work with rhel8 releases any longer - selinux disabled 1.6.1.4 - logrotate - 4.3.x -- updated to rhel8cis v2.0 benchamrk requirements +- updated to rhel8cis v2.0 benchmark requirements - removed iptables firewall controls (not valid on rhel9) -- added more to logrotate 4.3.x - sure to logrotate now a seperate package +- added more to logrotate 4.3.x - sure to logrotate now a separate package - grub path now standard to /boot/grub2/grub.cfg -- 1.6.1.4 from rh8 removed as selinux.cfg doesnt disable selinux any longer +- 1.6.1.4 from rh8 removed as selinux.cfg doesn't disable selinux any longer - workflow update - removed doc update diff --git a/defaults/main.yml b/defaults/main.yml index 8609e56..871e85e 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -116,7 +116,7 @@ audit_log_dir: '/opt' fetch_audit_output: false # Method of getting,uploading the summary files -## Ensure access and permissions are avaiable for these to occur. +## Ensure access and permissions are available for these to occur. ## options are # fetch - fetches from server and moves to location on the ansible controller (could be a mount point available to controller) # copy - copies file to a location available to the managed node @@ -587,7 +587,7 @@ rhel9cis_crypto_policy_module: '' # - 1.7.2 - Ensure local login warning banner is configured properly # - 1.7.3 - Ensure remote login warning banner is configured properly # This variable stores the content for the Warning Banner(relevant for issue, issue.net, motd). -rhel9cis_warning_banner: Authorized uses only. All activity may be monitored and reported. +rhel9cis_warning_banner: Authorized users only. All activity may be monitored and reported. # End Banner ## Control 1.8.x - Settings for GDM diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index d784dc1..53293e7 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -1,4 +1,5 @@ --- + - name: Pre Audit Setup | Set audit package name block: - name: Pre Audit Setup | Set audit package name | 64bit diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index 39c9f7d..845d9d9 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -1,4 +1,5 @@ --- + - name: Audit_Only | Create local Directories for hosts when: fetch_audit_files ansible.builtin.file: diff --git a/tasks/main.yml b/tasks/main.yml index e285e8d..f9f2bd2 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -17,9 +17,7 @@ success_msg: "This role is running a supported version of ansible {{ ansible_version.full }} >= {{ min_ansible_version }}" - name: "Setup rules if container" - when: - - ansible_connection == 'docker' or - ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] + when: ansible_connection == 'docker' or ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] tags: - container_discovery - always diff --git a/tasks/post.yml b/tasks/post.yml index 383cdf6..b6efdfe 100644 --- a/tasks/post.yml +++ b/tasks/post.yml @@ -28,8 +28,7 @@ - name: POST | reboot system if changes require it and not skipped when: change_requires_reboot - tags: - - always + tags: always vars: warn_control_id: Reboot_required block: diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 1ec355b..84db55a 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -200,7 +200,7 @@ tags: - always block: - - name: "PRELIM | AUDIT | Discover is wirelss adapter on system" + - name: "PRELIM | AUDIT | Discover is wireless adapter on system" ansible.builtin.command: find /sys/class/net/*/ -type d -name wireless register: discover_wireless_adapters changed_when: false diff --git a/vars/is_container.yml b/vars/is_container.yml index 1a69784..b49f770 100644 --- a/vars/is_container.yml +++ b/vars/is_container.yml @@ -2,7 +2,7 @@ # File to skip controls if container # Based on standard image no changes -# it expected all pkgs required for the container are alreday installed +# it expected all pkgs required for the container are already installed ## controls From e9babc8e3b3fa1d2e19b784980cb0e26c0cfc457 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 23 May 2025 14:22:49 +0100 Subject: [PATCH 008/116] added ignore comments in file Signed-off-by: Mark Bolwell --- tasks/parse_etc_password.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 86c1cac..70f79c6 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -4,7 +4,7 @@ tags: always block: - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd" - ansible.builtin.command: cat /etc/passwd + ansible.builtin.command: cat /etc/passwd | grep -v '^#' changed_when: false check_mode: false register: prelim_passwd_file_audit From de45131085ff33d7748ba58e4e2109ab19f6e89d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 23 May 2025 14:25:22 +0100 Subject: [PATCH 009/116] added rhel9cis_rsyslog_ansiblemanage conditional Signed-off-by: Mark Bolwell --- tasks/section_6/main.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tasks/section_6/main.yml b/tasks/section_6/main.yml index dda7ee5..dbff078 100644 --- a/tasks/section_6/main.yml +++ b/tasks/section_6/main.yml @@ -20,7 +20,9 @@ file: cis_6.2.2.x.yml - name: "SECTION | 6.2.3 | Configure rsyslog" - when: rhel9cis_syslog == 'rsyslog' + when: + - rhel9cis_syslog == 'rsyslog' + - rhel9cis_rsyslog_ansiblemanaged ansible.builtin.import_tasks: file: cis_6.2.3.x.yml From b9a59b9adc8a58449b487a27135a1dd625f894b9 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 23 May 2025 14:30:30 +0100 Subject: [PATCH 010/116] added check_mode logic Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.1.x.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index c000fe1..a162da1 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -58,6 +58,10 @@ dest: /var/lib/aide/aide.db.gz remote_src: true mode: 'ug-wx,o-rwx' + register: aide_db_cp + failed_when: + - not ansible_check_mode + - aide_db_cp.failed - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked" when: @@ -120,3 +124,7 @@ /usr/sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512 /usr/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512 validate: aide -D --config %s + register: aide_file_integrity_check + failed_when: + - not ansible_check_mode + - aide_file_integrity_check.failed From c23bce5c75a8418b547b6417a3ff645a41c493e0 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 23 May 2025 14:35:50 +0100 Subject: [PATCH 011/116] added check mode logic Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 84db55a..a0fc2fe 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -25,6 +25,7 @@ ansible.builtin.shell: > grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false" && $7 != "/dev/null") { print $1 }' changed_when: false + check_mode: false register: prelim_interactive_usernames - name: "PRELIM | AUDIT | Interactive User accounts home directories" @@ -32,6 +33,7 @@ ansible.builtin.shell: > grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $6 }' changed_when: false + check_mode: false register: prelim_interactive_users_home - name: "PRELIM | AUDIT | Interactive UIDs" @@ -39,6 +41,7 @@ ansible.builtin.shell: > grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $3 }' changed_when: false + check_mode: false register: prelim_interactive_uids - name: "PRELIM | AUDIT | Capture /etc/password variables" @@ -64,6 +67,7 @@ ansible.builtin.shell: | mount | awk '{print $1, $3, $5, $6}' changed_when: false + check_mode: false register: prelim_mount_output - name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options - build fact # This is inherited and used in mountpoints tasks @@ -100,6 +104,7 @@ ansible.builtin.command: rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' # noqa command-instead-of-module changed_when: false failed_when: false + check_mode: false register: prelim_check_gpg_imported - name: "PRELIM | AUDIT | Import gpg keys | Check Package" # noqa command-instead-of-module @@ -200,7 +205,7 @@ tags: - always block: - - name: "PRELIM | AUDIT | Discover is wireless adapter on system" + - name: "PRELIM | AUDIT | Discover is wirelss adapter on system" ansible.builtin.command: find /sys/class/net/*/ -type d -name wireless register: discover_wireless_adapters changed_when: false @@ -320,24 +325,29 @@ patterns: '*.conf,*.rules' register: prelim_auditd_conf_files -- name: "PRELIM | AUDIT | Discover Interactive UID MIN and MIN from logins.def" +- name: "PRELIM | AUDIT | Discover Interactive UID_MIN and UID_MAX from /etc/login.defs" when: rhel9cis_discover_int_uid tags: always block: - - name: "PRELIM | AUDIT | Capture UID_MIN information from logins.def" - ansible.builtin.shell: grep -w "^UID_MIN" /etc/login.defs | awk '{print $NF}' + - name: "PRELIM | AUDIT | Capture UID_MIN from /etc/login.defs" + ansible.builtin.command: awk '/^UID_MIN/ {print $2}' /etc/login.defs changed_when: false + failed_when: false + check_mode: false register: prelim_uid_min_id - - name: "PRELIM | AUDIT | Capture UID_MAX information from logins.def" - ansible.builtin.shell: grep -w "^UID_MAX" /etc/login.defs | awk '{print $NF}' + - name: "PRELIM | AUDIT | Capture UID_MAX from /etc/login.defs" + ansible.builtin.command: awk '/^UID_MAX/ {print $2}' /etc/login.defs changed_when: false + failed_when: false + check_mode: false register: prelim_uid_max_id - - name: "PRELIM | AUDIT | Set Fact for interactive uid/gid" - ansible.builtin.set_fact: - prelim_min_int_uid: "{{ prelim_uid_min_id.stdout }}" - prelim_max_int_uid: "{{ prelim_uid_max_id.stdout }}" +- name: "PRELIM | AUDIT | Set facts for interactive UID/GID ranges" + tags: always + ansible.builtin.set_fact: + prelim_min_int_uid: "{{ prelim_uid_min_id.stdout | default(min_int_uid) }}" + prelim_max_int_uid: "{{ prelim_uid_max_id.stdout | default(max_int_uid) }}" - name: "PRELIM | AUDIT | Gather the package facts after prelim" tags: From 4357f132a9ecce9ae0aa3788be7f83e7e404da33 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 23 May 2025 15:50:41 +0100 Subject: [PATCH 012/116] improved test for passwd entries Signed-off-by: Mark Bolwell --- tasks/parse_etc_password.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 70f79c6..9190421 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -4,7 +4,7 @@ tags: always block: - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd" - ansible.builtin.command: cat /etc/passwd | grep -v '^#' + ansible.builtin.shell: cat /etc/passwd | grep -v '^#' changed_when: false check_mode: false register: prelim_passwd_file_audit From cc48a0d0b53aa06c7377d80aa103bb6ad7daa06b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 23 May 2025 15:53:03 +0100 Subject: [PATCH 013/116] Interactive user discovery improve thanks to @polski-g Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 14 ++++++-------- tasks/section_5/cis_5.4.1.x.yml | 8 ++++---- tasks/section_5/cis_5.4.2.x.yml | 4 ++-- tasks/section_7/cis_7.2.x.yml | 8 ++++---- vars/main.yml | 3 +++ 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index a0fc2fe..9b19bf1 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -23,18 +23,16 @@ - name: "PRELIM | AUDIT | Interactive Users" tags: always ansible.builtin.shell: > - grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false" && $7 != "/dev/null") { print $1 }' + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false" && $7 != "/dev/null") { print $1":"$3":"$6 }' changed_when: false check_mode: false - register: prelim_interactive_usernames + register: prelim_interactive_users_raw -- name: "PRELIM | AUDIT | Interactive User accounts home directories" +- name: "PRELIM | AUDIT | Interactive Users (reformat)" tags: always - ansible.builtin.shell: > - grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $6 }' - changed_when: false - check_mode: false - register: prelim_interactive_users_home + ansible.builtin.set_fact: + prelim_interactive_usernames: "{{ prelim_interactive_users | default([]) + [dict([('username', item.split(':')[0]), ('uid', item.split(':')[1]), ('home', item.split(':')[2])])] }}" + loop: "{{ prelim_interactive_users_raw.stdout_lines }}" - name: "PRELIM | AUDIT | Interactive UIDs" tags: always diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index 6a492e5..1962101 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -29,7 +29,7 @@ - name: "5.4.1.1 | PATCH | Ensure password expiration is 365 days or less | Set existing users PASS_MAX_DAYS" when: - discovered_max_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames.stdout + - item in prelim_interactive_usernames | map(attribute='username') | list - rhel9cis_force_user_maxdays ansible.builtin.user: name: "{{ item }}" @@ -60,7 +60,7 @@ - name: "5.4.1.2 | PATCH | Ensure minimum password days is configured | Set existing users PASS_MIN_DAYS" when: - discovered_min_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames.stdout + - item in prelim_interactive_usernames | map(attribute='username') | list - rhel9cis_force_user_mindays ansible.builtin.user: name: "{{ item }}" @@ -91,7 +91,7 @@ - name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured | Set existing users WARN_DAYS" when: - discovered_warn_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames.stdout + - item in prelim_interactive_usernames | map(attribute='username') | list - rhel9cis_force_user_warnage ansible.builtin.command: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" changed_when: true @@ -140,7 +140,7 @@ register: discovered_passwdlck_user_list - name: "5.4.1.5 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts" - when: item in prelim_interactive_usernames.stdout + when: item in prelim_interactive_usernames | map(attribute='username') | list ansible.builtin.command: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}" changed_when: true loop: "{{ discovered_passwdlck_user_list.stdout_lines }}" diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index 12390b3..a8eb4d0 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -195,7 +195,7 @@ - name: "5.4.2.7 | PATCH | Ensure system accounts do not have a valid login shell" when: - rhel9cis_rule_5_4_2_7 - - "item.id not in prelim_interactive_usernames.stdout" + - "item.id not in prelim_interactive_usernames | map(attribute='username')" - item.id not in rhel9cis_system_users_shell - "'root' not in item.id" - rhel9cis_disruption_high @@ -220,7 +220,7 @@ when: - rhel9cis_rule_5_4_2_8 - rhel9cis_disruption_high - - "item.id not in prelim_interactive_usernames.stdout" + - "item.id not in prelim_interactive_usernames | map(attribute='username')" - "'root' not in item.id" tags: - level1-server diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml index cc1825c..8706877 100644 --- a/tasks/section_7/cis_7.2.x.yml +++ b/tasks/section_7/cis_7.2.x.yml @@ -256,7 +256,7 @@ etype: group permissions: rx state: present - loop: "{{ prelim_interactive_users_home.stdout_lines }}" + loop: "{{ prelim_interactive_users | map(attribute='home') | list }}" - name: "7.2.8 | PATCH | Ensure local interactive user home directories are configured | Set other ACL" when: not system_is_container @@ -266,7 +266,7 @@ etype: other permissions: 0 state: present - loop: "{{ prelim_interactive_users_home.stdout_lines }}" + loop: "{{ prelim_interactive_users | map(attribute='home') | list }}" - name: "7.2.9 | PATCH | Ensure local interactive user dot files access is configured" when: @@ -315,6 +315,6 @@ ansible.builtin.file: path: '{{ item }}' mode: 'go-w' - owner: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" - group: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" + owner: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_raw.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" + group: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_raw.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" with_items: "{{ discovered_homedir_hidden_files.stdout_lines }}" diff --git a/vars/main.yml b/vars/main.yml index cdca90d..5eed07c 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -22,6 +22,9 @@ rhel9cis_allowed_crypto_policies_modules: warn_control_list: "" warn_count: 0 +# list of dicts of interactive users, filled in during prelim.yml +prelim_interactive_users: [] + # Default empty values for 1.4.2 efi_mount_opts_addition: '' From a16b6b96bce765cc1d6971bcee3e3021b56db719 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Fri, 23 May 2025 11:14:58 -0400 Subject: [PATCH 014/116] Fix for #325 thank you @mindrb Signed-off-by: Frederick Witty --- Changelog.md | 1 + tasks/section_6/cis_6.2.2.1.x.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index d9aa825..d09b13d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,7 @@ ## 2.0.0 - Based on CIS v2.0.0 +- #325 - thanks to @mindrb - May 2025 QA Fixes - Typo fixes and Banner verbiage diff --git a/tasks/section_6/cis_6.2.2.1.x.yml b/tasks/section_6/cis_6.2.2.1.x.yml index 945c2e4..aa2415d 100644 --- a/tasks/section_6/cis_6.2.2.1.x.yml +++ b/tasks/section_6/cis_6.2.2.1.x.yml @@ -35,7 +35,7 @@ regexp: "{{ item.regexp }}" line: "{{ item.line }}" loop: - - { regexp: 'URL=', line: 'URL={{ rhel9cis_remote_log_server }}'} + - { regexp: 'URL=', line: 'URL={{ rhel9cis_journal_upload_url }}'} - { regexp: 'ServerKeyFile=', line: 'ServerKeyFile={{ rhel9cis_journal_upload_serverkeyfile }}'} - { regexp: 'ServerCertificateFile=', line: 'ServerCertificateFile={{ rhel9cis_journal_servercertificatefile }}'} - { regexp: 'TrustedCertificateFile=', line: 'TrustedCertificateFile={{ rhel9cis_journal_trustedcertificatefile }}'} From a1126618a7b22475921834e166d339707ab04e3b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 10:52:32 +0100 Subject: [PATCH 015/116] Added names Signed-off-by: Mark Bolwell --- .pre-commit-config.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 331d150..c25682f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,16 +39,16 @@ repos: rev: v1.5.0 hooks: - id: detect-secrets - name: Detect Secrets + name: Detect Secrets test - repo: https://github.com/gitleaks/gitleaks - rev: v8.24.3 + rev: v8.26.0 hooks: - id: gitleaks - name: GitLeaks + name: Run Gitleaks test - repo: https://github.com/ansible-community/ansible-lint - rev: v25.2.1 + rev: v25.5.0 hooks: - id: ansible-lint name: Ansible-lint @@ -67,7 +67,7 @@ repos: # - ansible-core>=2.10.1 - repo: https://github.com/adrienverge/yamllint.git - rev: v1.37.0 # or higher tag + rev: v1.37.1 # or higher tag hooks: - id: yamllint name: Check YAML Lint From f29fc9088cc8a31314bf0d00b37872daf10bb5b8 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 10:53:32 +0100 Subject: [PATCH 016/116] fixed var naming Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 4 ++-- tasks/section_5/cis_5.4.1.x.yml | 8 ++++---- tasks/section_5/cis_5.4.2.x.yml | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 9b19bf1..7d3b295 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -31,7 +31,7 @@ - name: "PRELIM | AUDIT | Interactive Users (reformat)" tags: always ansible.builtin.set_fact: - prelim_interactive_usernames: "{{ prelim_interactive_users | default([]) + [dict([('username', item.split(':')[0]), ('uid', item.split(':')[1]), ('home', item.split(':')[2])])] }}" + prelim_interactive_users: "{{ prelim_interactive_users | default([]) + [dict([('username', item.split(':')[0]), ('uid', item.split(':')[1]), ('home', item.split(':')[2])])] }}" loop: "{{ prelim_interactive_users_raw.stdout_lines }}" - name: "PRELIM | AUDIT | Interactive UIDs" @@ -203,7 +203,7 @@ tags: - always block: - - name: "PRELIM | AUDIT | Discover is wirelss adapter on system" + - name: "PRELIM | AUDIT | Discover is wireless adapter on system" ansible.builtin.command: find /sys/class/net/*/ -type d -name wireless register: discover_wireless_adapters changed_when: false diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index 1962101..7fcfb0b 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -29,7 +29,7 @@ - name: "5.4.1.1 | PATCH | Ensure password expiration is 365 days or less | Set existing users PASS_MAX_DAYS" when: - discovered_max_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames | map(attribute='username') | list + - item in prelim_interactive_users | map(attribute='username') | list - rhel9cis_force_user_maxdays ansible.builtin.user: name: "{{ item }}" @@ -60,7 +60,7 @@ - name: "5.4.1.2 | PATCH | Ensure minimum password days is configured | Set existing users PASS_MIN_DAYS" when: - discovered_min_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames | map(attribute='username') | list + - item in prelim_interactive_users | map(attribute='username') | list - rhel9cis_force_user_mindays ansible.builtin.user: name: "{{ item }}" @@ -91,7 +91,7 @@ - name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured | Set existing users WARN_DAYS" when: - discovered_warn_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames | map(attribute='username') | list + - item in prelim_interactive_users | map(attribute='username') | list - rhel9cis_force_user_warnage ansible.builtin.command: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" changed_when: true @@ -140,7 +140,7 @@ register: discovered_passwdlck_user_list - name: "5.4.1.5 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts" - when: item in prelim_interactive_usernames | map(attribute='username') | list + when: item in prelim_interactive_users | map(attribute='username') | list ansible.builtin.command: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}" changed_when: true loop: "{{ discovered_passwdlck_user_list.stdout_lines }}" diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index a8eb4d0..26985a3 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -195,7 +195,7 @@ - name: "5.4.2.7 | PATCH | Ensure system accounts do not have a valid login shell" when: - rhel9cis_rule_5_4_2_7 - - "item.id not in prelim_interactive_usernames | map(attribute='username')" + - "item.id not in prelim_interactive_users | map(attribute='username')" - item.id not in rhel9cis_system_users_shell - "'root' not in item.id" - rhel9cis_disruption_high @@ -220,7 +220,7 @@ when: - rhel9cis_rule_5_4_2_8 - rhel9cis_disruption_high - - "item.id not in prelim_interactive_usernames | map(attribute='username')" + - "item.id not in prelim_interactive_users | map(attribute='username')" - "'root' not in item.id" tags: - level1-server From 97abfaf9f81bf040441d5287970777b6b4d1be8e Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 15:41:12 +0100 Subject: [PATCH 017/116] updated passwd variable Signed-off-by: Mark Bolwell --- tasks/parse_etc_password.yml | 8 ++++---- tasks/section_5/cis_5.4.2.x.yml | 4 ++-- tasks/section_7/cis_7.2.x.yml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 9190421..c7ed865 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -7,12 +7,12 @@ ansible.builtin.shell: cat /etc/passwd | grep -v '^#' changed_when: false check_mode: false - register: prelim_passwd_file_audit + register: prelim_capture_passwd_file - - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries" + - name: "PRELIM | 5.4.2 | 7.2.8 | Split passwd entries" ansible.builtin.set_fact: - rhel9cis_passwd: "{{ prelim_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" - loop: "{{ prelim_passwd_file_audit.stdout_lines }}" + prelim_captured_passwd_data: "{{ prelim_capture_passwd_file.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" + loop: "{{ prelim_capture_passwd_file.stdout_lines }}" vars: ld_passwd_regex: >- ^(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*) diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index 26985a3..37a4e11 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -212,7 +212,7 @@ ansible.builtin.user: name: "{{ item.id }}" shell: /usr/sbin/nologin - loop: "{{ rhel9cis_passwd }}" + loop: "{{ prelim_captured_passwd_data }}" loop_control: label: "{{ item.id }}" @@ -235,6 +235,6 @@ ansible.builtin.user: name: "{{ item.id }}" password_lock: true - loop: "{{ rhel9cis_passwd }}" + loop: "{{ prelim_captured_passwd_data }}" loop_control: label: "{{ item.id }}" diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml index 8706877..a5e0a25 100644 --- a/tasks/section_7/cis_7.2.x.yml +++ b/tasks/section_7/cis_7.2.x.yml @@ -243,7 +243,7 @@ state: directory owner: "{{ item.id }}" group: "{{ item.gid }}" - loop: "{{ rhel9cis_passwd | selectattr('uid', '>=', prelim_min_int_uid | int) | selectattr('uid', '<=', prelim_max_int_uid | int) | list }}" + loop: "{{ prelim_captured_passwd_data | selectattr('uid', '>=', prelim_min_int_uid | int) | selectattr('uid', '<=', prelim_max_int_uid | int) | list }}" loop_control: label: "{{ item.id }}" @@ -315,6 +315,6 @@ ansible.builtin.file: path: '{{ item }}' mode: 'go-w' - owner: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_raw.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" - group: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_raw.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" + owner: "{{ prelim_captured_passwd_data | selectattr('dir', 'in', prelim_interactive_users_raw.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" + group: "{{ prelim_captured_passwd_data | selectattr('dir', 'in', prelim_interactive_users_raw.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" with_items: "{{ discovered_homedir_hidden_files.stdout_lines }}" From 7673c2ff00bb3b9716d602ed6a57665e4e7814c9 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 15:53:41 +0100 Subject: [PATCH 018/116] Added home directory discovery Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 7d3b295..4c170a1 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -34,6 +34,14 @@ prelim_interactive_users: "{{ prelim_interactive_users | default([]) + [dict([('username', item.split(':')[0]), ('uid', item.split(':')[1]), ('home', item.split(':')[2])])] }}" loop: "{{ prelim_interactive_users_raw.stdout_lines }}" +- name: "PRELIM | AUDIT | Interactive User accounts home directories" + tags: always + ansible.builtin.shell: > + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false" && $7 != "/dev/null") { print $6 }' + changed_when: false + check_mode: false + register: prelim_interactive_users_home + - name: "PRELIM | AUDIT | Interactive UIDs" tags: always ansible.builtin.shell: > From 260005415c91ba6059df3bc13938a04904321a36 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 15:58:54 +0100 Subject: [PATCH 019/116] Aligned with public Signed-off-by: Mark Bolwell --- .pre-commit-config.yaml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 331d150..ebc85d7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,16 +39,14 @@ repos: rev: v1.5.0 hooks: - id: detect-secrets - name: Detect Secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.24.3 + rev: v8.26.0 hooks: - id: gitleaks - name: GitLeaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.2.1 + rev: v25.4.0 hooks: - id: ansible-lint name: Ansible-lint @@ -67,7 +65,7 @@ repos: # - ansible-core>=2.10.1 - repo: https://github.com/adrienverge/yamllint.git - rev: v1.37.0 # or higher tag + rev: v1.37.1 # or higher tag hooks: - id: yamllint name: Check YAML Lint From f2c03f1e687067e52671eefc86354b1de422097d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 16:11:36 +0100 Subject: [PATCH 020/116] variable networkmanager package and typo fixes Signed-off-by: Mark Bolwell --- defaults/main.yml | 11 ++++++----- tasks/section_3/cis_3.1.x.yml | 8 ++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 871e85e..cc49b0a 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -12,7 +12,7 @@ os_check: true # Disruption is high ## Run tests that are considered higher risk and could have a system impact if not properly tested ## Default false -## Will be fine if clean new unconfigured build +## Will be fine if clean new un configured build rhel9cis_disruption_high: false ## Switching on/off specific baseline sections @@ -513,7 +513,7 @@ rhel9cis_rule_7_2_9: true ## Section 1 vars -## Ability to enabe debug on mounts to assist in troubleshooting +## Ability to enable debug on mounts to assist in troubleshooting # Mount point changes are set based upon facts created in Prelim # these then build the variable and options that is passed to the handler to set the mount point for the controls in section1. rhel9cis_debug_mount_data: false @@ -723,6 +723,7 @@ rhel9cis_ipv6_required: true ## 3.1.2 wireless network requirements # if wireless adapter found allow network manager to be installed rhel9cis_install_network_manager: false +rhel9cis_network_manager_package_name: NetworkManager # 3.3 System network parameters (host only OR host and router) # This variable governs whether specific CIS rules # concerned with acceptance and routing of packages are skipped. @@ -815,7 +816,7 @@ rhel9cis_sshd_clientalivecountmax: 3 rhel9cis_sshd_clientaliveinterval: 15 ## Control 5.1.12 - disable forwarding -# By Default this will also disablex11 forwarding +# By Default this will also disable x11 forwarding # set 'yes' if x11 is required this can be changed to run in /etc/ssh/ssh_config.d/50-redhat.conf rhel9cis_sshd_x11forwarding: 'no' @@ -1045,14 +1046,14 @@ rhel9cis_bash_umask: '0027' # 0027 or more restrictive # These are discovered via logins.def if set true rhel9cis_discover_int_uid: true # This variable sets the minimum number from which to search for UID -# Note that the value will be dynamically overwritten if variable `dicover_int_uid` has +# Note that the value will be dynamically overwritten if variable `discover_int_uid` has # been set to `true`. min_int_uid: 1000 ### Controls: # - Ensure local interactive user home directories exist # - Ensure local interactive users own their home directories # This variable sets the maximum number at which the search stops for UID -# Note that the value will be dynamically overwritten if variable `dicover_int_uid` has +# Note that the value will be dynamically overwritten if variable `discover_int_uid` has # been set to `true`. max_int_uid: 65533 diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index 68a66de..a20c0e9 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -39,7 +39,7 @@ warn_control_id: '3.1.2' block: - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Check for network-manager tool" - when: "'network-manager' in ansible_facts.packages" + when: "rhel9cis_network_manager_package_name in ansible_facts.packages" ansible.builtin.command: nmcli radio wifi changed_when: false failed_when: false @@ -48,19 +48,19 @@ - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Disable wireless if network-manager installed" when: - - "'network-manager' in ansible_facts.packages" + - "rhel9cis_network_manager_package_name in ansible_facts.packages" - "'enabled' in discovered_wifi_status.stdout" ansible.builtin.command: nmcli radio all off changed_when: discovered_nmcli_radio_off.rc == 0 register: discovered_nmcli_radio_off - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Warn about wireless if network-manager not installed" - when: "'network-manager' not in ansible_facts.packages" + when: "rhel9cis_network_manager_package_name not in ansible_facts.packages" ansible.builtin.debug: msg: "Warning!! You need to disable wireless interfaces manually since network-manager is not installed" - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Set warning count" - when: "'network-manager' not in ansible_facts.packages" + when: "rhel9cis_network_manager_package_name not in ansible_facts.packages" ansible.builtin.import_tasks: file: warning_facts.yml From 2256456f0e6979d7cd906e648671d940105cb166 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 16:12:31 +0100 Subject: [PATCH 021/116] align with public fixes Signed-off-by: Mark Bolwell --- tasks/audit_only.yml | 10 ---------- tasks/main.yml | 4 +++- tasks/prelim.yml | 20 ++++++++++++++++++-- tasks/section_5/cis_5.1.x.yml | 2 ++ tasks/section_7/cis_7.2.x.yml | 2 +- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index 845d9d9..d6f20ea 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -1,15 +1,5 @@ --- -- name: Audit_Only | Create local Directories for hosts - when: fetch_audit_files - ansible.builtin.file: - mode: 'u+x,go-w' - path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}" - recurse: true - state: directory - delegate_to: localhost - become: false - - name: Audit_only | Show Audit Summary when: audit_only ansible.builtin.debug: diff --git a/tasks/main.yml b/tasks/main.yml index f9f2bd2..f099e06 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -17,7 +17,9 @@ success_msg: "This role is running a supported version of ansible {{ ansible_version.full }} >= {{ min_ansible_version }}" - name: "Setup rules if container" - when: ansible_connection == 'docker' or ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] + when: + - ansible_connection == 'docker' or + ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container" tags: - container_discovery - always diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 9b19bf1..ced76ce 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -31,9 +31,17 @@ - name: "PRELIM | AUDIT | Interactive Users (reformat)" tags: always ansible.builtin.set_fact: - prelim_interactive_usernames: "{{ prelim_interactive_users | default([]) + [dict([('username', item.split(':')[0]), ('uid', item.split(':')[1]), ('home', item.split(':')[2])])] }}" + prelim_interactive_users: "{{ prelim_interactive_users | default([]) + [dict([('username', item.split(':')[0]), ('uid', item.split(':')[1]), ('home', item.split(':')[2])])] }}" loop: "{{ prelim_interactive_users_raw.stdout_lines }}" +- name: "PRELIM | AUDIT | Interactive User accounts home directories" + tags: always + ansible.builtin.shell: > + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false" && $7 != "/dev/null") { print $6 }' + changed_when: false + check_mode: false + register: prelim_interactive_users_home + - name: "PRELIM | AUDIT | Interactive UIDs" tags: always ansible.builtin.shell: > @@ -203,7 +211,7 @@ tags: - always block: - - name: "PRELIM | AUDIT | Discover is wirelss adapter on system" + - name: "PRELIM | AUDIT | Discover is wireless adapter on system" ansible.builtin.command: find /sys/class/net/*/ -type d -name wireless register: discover_wireless_adapters changed_when: false @@ -246,6 +254,14 @@ mode: 'go-rwx' state: touch +- name: "PRELIM | PATCH | sshd_config.d/50-redhat.conf exists" + when: + - rhel9cis_rule_5_1_10 or + rhel9cis_rule_5_1_11 + ansible.builtin.stat: + path: /etc/ssh/sshd_config.d/50-redhat.conf + register: discovered_sshd_50_redhat_file + - name: "PRELIM | AUDIT | Capture pam security related files" tags: always ansible.builtin.find: diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index 99176fd..eaee7de 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -276,6 +276,7 @@ notify: Restart sshd - name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled | override" + when: discovered_sshd_50_redhat_file.stat.exists ansible.builtin.lineinfile: path: /etc/ssh/sshd_config.d/50-redhat.conf regexp: ^(?i)(#|)\s*X11Forwarding @@ -298,6 +299,7 @@ - NIST800-53R5_IA-5 block: - name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled | redhat file" + when: discovered_sshd_50_redhat_file.stat.exists ansible.builtin.lineinfile: path: /etc/ssh/sshd_config.d/50-redhat.conf regexp: ^(?i)(#|)\s*GSSAPIAuthentication diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml index 8706877..cb01c21 100644 --- a/tasks/section_7/cis_7.2.x.yml +++ b/tasks/section_7/cis_7.2.x.yml @@ -220,7 +220,7 @@ - name: "7.2.7 | AUDIT | Ensure no duplicate group names exist | Print warning about users with duplicate group names" when: discovered_group_check.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following group names are duplicates: {{ discovered_group_group_check.stdout_lines }}" + msg: "Warning!! The following group names are duplicates: {{ discovered_group_check.stdout_lines }}" - name: "7.2.7 | AUDIT | Ensure no duplicate group names exist | Set warning count" when: discovered_group_check.stdout | length > 0 From 2e3499ca8c6125ba237779ddb709889370583fd2 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 16:47:01 +0100 Subject: [PATCH 022/116] added missing square brace Signed-off-by: Mark Bolwell --- tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/main.yml b/tasks/main.yml index f099e06..e285e8d 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -19,7 +19,7 @@ - name: "Setup rules if container" when: - ansible_connection == 'docker' or - ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container" + ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] tags: - container_discovery - always From f40d17df92588a7e97655fa9691805fd17b93c59 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Thu, 12 Jun 2025 12:42:44 -0400 Subject: [PATCH 023/116] Update eprep based tasks to grep/awk Signed-off-by: Frederick Witty --- tasks/main.yml | 2 +- tasks/section_1/cis_1.3.1.x.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index e285e8d..fe50b10 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -132,7 +132,7 @@ - rule_5.4.2.4 block: - name: "Ensure root password is set" - ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)" + ansible.builtin.shell: passwd -S root | grep -E "(Password set, SHA512 crypt|Password locked)" changed_when: false register: prelim_root_passwd_set diff --git a/tasks/section_1/cis_1.3.1.x.yml b/tasks/section_1/cis_1.3.1.x.yml index 198ae7b..17e138e 100644 --- a/tasks/section_1/cis_1.3.1.x.yml +++ b/tasks/section_1/cis_1.3.1.x.yml @@ -106,7 +106,7 @@ warn_control_id: '1.3.1.6' block: - name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist | Find the unconfined services" - ansible.builtin.shell: ps -eZ | grep unconfined_service_t | egrep -vw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }' + ansible.builtin.shell: ps -eZ | awk -F':'' '/unconfined_service_t/ && $NF !~ /tr|ps|egrep|bash|awk/ {print $NF}' register: discovered_unconf_services failed_when: false changed_when: false From 3a0ee6e9f8ccea92c22bf5838e0a514ae63c76b7 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Thu, 12 Jun 2025 15:44:03 -0400 Subject: [PATCH 024/116] update 1.3.1.6 log to grep -E Signed-off-by: Frederick Witty --- tasks/section_1/cis_1.3.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_1/cis_1.3.1.x.yml b/tasks/section_1/cis_1.3.1.x.yml index 17e138e..ad7d844 100644 --- a/tasks/section_1/cis_1.3.1.x.yml +++ b/tasks/section_1/cis_1.3.1.x.yml @@ -106,7 +106,7 @@ warn_control_id: '1.3.1.6' block: - name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist | Find the unconfined services" - ansible.builtin.shell: ps -eZ | awk -F':'' '/unconfined_service_t/ && $NF !~ /tr|ps|egrep|bash|awk/ {print $NF}' + ansible.builtin.shell: ps -eZ | grep unconfined_service_t | grep -Evw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }' register: discovered_unconf_services failed_when: false changed_when: false From 27c7ec3604c5d56520d4b2ea06d8ccc3df381f60 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 17:12:21 +0100 Subject: [PATCH 025/116] fixed typos Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.2.3.x.yml | 4 ++-- tasks/section_1/cis_1.1.2.4.x.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml index 998d1ba..635648d 100644 --- a/tasks/section_1/cis_1.1.2.3.x.yml +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -21,12 +21,12 @@ register: discovered_home_mount - name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | Absent" - when: discovered_dev_shm_mount is undefined + when: discovered_home_mount is undefined ansible.builtin.debug: msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" - name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | Present" - when: discovered_dev_shm_mount is undefined + when: discovered_home_mount is undefined ansible.builtin.import_tasks: file: warning_facts.yml diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml index e0afd4e..f89fe3f 100644 --- a/tasks/section_1/cis_1.1.2.4.x.yml +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -22,12 +22,12 @@ register: discovered_var_mount - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Absent" - when: discovered_dev_shm_mount is undefined + when: discovered_var_mount is undefined ansible.builtin.debug: msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Present" - when: discovered_dev_shm_mount is undefined + when: discovered_var_mount is undefined ansible.builtin.import_tasks: file: warning_facts.yml From 6770e5a4ffbad121b1a59c7d91acd804aac087f5 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 17:13:53 +0100 Subject: [PATCH 026/116] added check_mode false to task Signed-off-by: Mark Bolwell --- tasks/auditd.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/auditd.yml b/tasks/auditd.yml index 7b86b94..0fa0b32 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -7,6 +7,7 @@ - name: "POST | AUDITD | Set supported_syscalls variable" ansible.builtin.shell: ausyscall --dump | awk '{print $2}' changed_when: false + check_mode: false failed_when: discovered_auditd_syscalls.rc not in [ 0, 1 ] register: discovered_auditd_syscalls From ce3ae8361e1aec615b4168bacd1e5bc964f06fc8 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 17:14:58 +0100 Subject: [PATCH 027/116] Updated logic for root password check Signed-off-by: Mark Bolwell --- tasks/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasks/main.yml b/tasks/main.yml index e285e8d..43ec09c 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -132,8 +132,9 @@ - rule_5.4.2.4 block: - name: "Ensure root password is set" - ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)" + ansible.builtin.shell: passwd -S root | grep -E "(Password set, SHA512 crypt|Password locked)" changed_when: false + failed_when: prelim_root_passwd_set.rc not in [ 0, 1 ] register: prelim_root_passwd_set - name: "Ensure root password is set" From 2eb85294c83f3c54a9c57a355f9b8609258c628c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 17:15:42 +0100 Subject: [PATCH 028/116] Updated conditionals for audit steps Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index ced76ce..2e0dd95 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -4,9 +4,7 @@ # List users in order to look files inside each home directory - name: "PRELIM | Include audit specific variables" - when: - - run_audit or audit_only - - setup_audit + when: run_audit or audit_only or setup_audit tags: - setup_audit - run_audit @@ -14,9 +12,7 @@ file: audit.yml - name: "PRELIM | Include pre-remediation audit tasks" - when: - - run_audit or audit_only - - setup_audit + when: run_audit or audit_only or setup_audit tags: run_audit ansible.builtin.import_tasks: pre_remediation_audit.yml From 1537bf72dfa014f163ccfe1780bc9a0d899f3c57 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 17:16:26 +0100 Subject: [PATCH 029/116] 5-redhat.conf var naming Signed-off-by: Mark Bolwell --- Changelog.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Changelog.md b/Changelog.md index d09b13d..203a510 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,13 @@ # Changes to rhel9CIS + +## 2.0.1 - Based on CIS v2.0.0 + +- Thanks to @polski-g several issues and improvements added +- Improved testing for 50-redhat.conf for ssh +- 5.1.x regexp improvements +- Improved root password check + ## 2.0.0 - Based on CIS v2.0.0 - #325 - thanks to @mindrb From 2724faf1fc1b2934438b007e3822125953d98a78 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 17:17:00 +0100 Subject: [PATCH 030/116] 50-redhat.conf var naming update Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 2e0dd95..1eed552 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -256,7 +256,7 @@ rhel9cis_rule_5_1_11 ansible.builtin.stat: path: /etc/ssh/sshd_config.d/50-redhat.conf - register: discovered_sshd_50_redhat_file + register: prelim_sshd_50_redhat_file - name: "PRELIM | AUDIT | Capture pam security related files" tags: always From 02008339b4186099c8849a9f1bdf30312d65623e Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 17:18:22 +0100 Subject: [PATCH 031/116] updated regex Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.1.x.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index eaee7de..13ec292 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -279,7 +279,7 @@ when: discovered_sshd_50_redhat_file.stat.exists ansible.builtin.lineinfile: path: /etc/ssh/sshd_config.d/50-redhat.conf - regexp: ^(?i)(#|)\s*X11Forwarding + regexp: (?i)^(#|)\s*X11Forwarding line: 'X11Forwarding {{ rhel9cis_sshd_x11forwarding }}' validate: sshd -t -f %s notify: Restart sshd @@ -302,7 +302,7 @@ when: discovered_sshd_50_redhat_file.stat.exists ansible.builtin.lineinfile: path: /etc/ssh/sshd_config.d/50-redhat.conf - regexp: ^(?i)(#|)\s*GSSAPIAuthentication + regexp: (?i)^(#|)\s*GSSAPIAuthentication line: GSSAPIAuthentication no validate: sshd -t -f %s notify: Restart sshd @@ -310,7 +310,7 @@ - name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled | ssh config" ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*GSSAPIAuthentication + regexp: (?i)^(#|)\s*GSSAPIAuthentication line: GSSAPIAuthentication no validate: sshd -t -f %s notify: Restart sshd @@ -330,7 +330,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*HostbasedAuthentication + regexp: (?i)^(#|)\s*HostbasedAuthentication line: 'HostbasedAuthentication no' validate: sshd -t -f %s notify: Restart sshd @@ -350,7 +350,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*IgnoreRhosts + regexp: (?i)^(#|)\s*IgnoreRhosts line: 'IgnoreRhosts yes' insertbefore: "^Match" firstmatch: true @@ -368,7 +368,7 @@ - NIST800-53R5_CM-6 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*LoginGraceTime + regexp: (?i)^(#|)\s*LoginGraceTime line: "LoginGraceTime {{ rhel9cis_sshd_logingracetime }}" insertbefore: "^Match" firstmatch: true @@ -388,7 +388,7 @@ - NIST800-53R5_SI-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*LogLevel + regexp: (?i)^(#|)\s*LogLevel line: 'LogLevel {{ rhel9cis_ssh_loglevel }}' insertbefore: "^Match" firstmatch: true @@ -426,7 +426,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*MaxStartups + regexp: (?i)^(#|)\s*MaxStartups line: 'MaxStartups {{ rhel9cis_ssh_maxstartups }}' validate: sshd -t -f %s notify: Restart sshd @@ -446,7 +446,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*MaxSessions + regexp: (?i)^(#|)\s*MaxSessions line: 'MaxSessions {{ rhel9cis_ssh_maxsessions }}' validate: sshd -t -f %s notify: Restart sshd @@ -466,7 +466,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*PermitEmptyPasswords + regexp: (?i)^(#|)\s*PermitEmptyPasswords line: 'PermitEmptyPasswords no' validate: sshd -t -f %s notify: Restart sshd @@ -484,7 +484,7 @@ - name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled | config file" ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*PermitRootLogin + regexp: (?i)^(#|)\s*PermitRootLogin line: 'PermitRootLogin no' validate: sshd -t -f %s notify: Restart sshd @@ -510,7 +510,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*PermitUserEnvironment + regexp: (?i)^(#|)\s*PermitUserEnvironment line: 'PermitUserEnvironment no' validate: sshd -t -f %s notify: Restart sshd @@ -530,7 +530,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*UsePAM + regexp: (?i)^(#|)\s*UsePAM line: 'UsePAM yes' validate: sshd -t -f %s notify: Restart sshd From f892525a7cf43a48b887475f21f296552281050b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 17:19:18 +0100 Subject: [PATCH 032/116] 5.1.10 and 5.1.11 updated variable naming Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.1.x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index 13ec292..3fd366c 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -276,7 +276,7 @@ notify: Restart sshd - name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled | override" - when: discovered_sshd_50_redhat_file.stat.exists + when: prelim_sshd_50_redhat_file.stat.exists ansible.builtin.lineinfile: path: /etc/ssh/sshd_config.d/50-redhat.conf regexp: (?i)^(#|)\s*X11Forwarding @@ -299,7 +299,7 @@ - NIST800-53R5_IA-5 block: - name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled | redhat file" - when: discovered_sshd_50_redhat_file.stat.exists + when: prelim_sshd_50_redhat_file.stat.exists ansible.builtin.lineinfile: path: /etc/ssh/sshd_config.d/50-redhat.conf regexp: (?i)^(#|)\s*GSSAPIAuthentication From b65504de6b89f746812e5c251e8eccad621567c6 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 17:20:40 +0100 Subject: [PATCH 033/116] Updated egrep Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.3.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_1/cis_1.3.1.x.yml b/tasks/section_1/cis_1.3.1.x.yml index 198ae7b..ad7d844 100644 --- a/tasks/section_1/cis_1.3.1.x.yml +++ b/tasks/section_1/cis_1.3.1.x.yml @@ -106,7 +106,7 @@ warn_control_id: '1.3.1.6' block: - name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist | Find the unconfined services" - ansible.builtin.shell: ps -eZ | grep unconfined_service_t | egrep -vw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }' + ansible.builtin.shell: ps -eZ | grep unconfined_service_t | grep -Evw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }' register: discovered_unconf_services failed_when: false changed_when: false From 7e5fb97b9adb021bd4ecfa71939f8e1f8022865a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 17:23:28 +0100 Subject: [PATCH 034/116] updated Signed-off-by: Mark Bolwell --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 203a510..7542aa1 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ - Improved testing for 50-redhat.conf for ssh - 5.1.x regexp improvements - Improved root password check +- egrep command changed to grep -E ## 2.0.0 - Based on CIS v2.0.0 From 6ced990430e326cb9151046bb690c981fd49eb20 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Mon, 16 Jun 2025 14:58:21 -0400 Subject: [PATCH 035/116] Update handler naming change_requires_reboot to set reboot required Signed-off-by: Frederick Witty --- handlers/main.yml | 8 ++++---- tasks/prelim.yml | 8 ++------ tasks/section_1/cis_1.2.2.x.yml | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/handlers/main.yml b/handlers/main.yml index 1a3b66e..8ac3b22 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -150,7 +150,7 @@ ansible.posix.mount: path: "{{ mount_point }}" state: remounted - notify: Change_requires_reboot + notify: Set reboot required listen: "Remount /boot/efi" - name: Reload sysctl @@ -194,7 +194,7 @@ ansible.builtin.command: update-crypto-policies --set "{{ rhel9cis_full_crypto_policy }}" changed_when: true notify: - - Change_requires_reboot + - Set reboot required - Restart sshd - name: Restart firewalld @@ -255,7 +255,7 @@ when: discovered_auditd_immutable_check.stdout == '1' ansible.builtin.debug: msg: "Reboot required for auditd to apply new rules as immutable set" - notify: Change_requires_reboot + notify: Set reboot required - name: Stop auditd process ansible.builtin.command: systemctl kill auditd @@ -268,6 +268,6 @@ state: started listen: Restart auditd -- name: Change_requires_reboot +- name: Set reboot required ansible.builtin.set_fact: change_requires_reboot: true diff --git a/tasks/prelim.yml b/tasks/prelim.yml index ced76ce..2e0dd95 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -4,9 +4,7 @@ # List users in order to look files inside each home directory - name: "PRELIM | Include audit specific variables" - when: - - run_audit or audit_only - - setup_audit + when: run_audit or audit_only or setup_audit tags: - setup_audit - run_audit @@ -14,9 +12,7 @@ file: audit.yml - name: "PRELIM | Include pre-remediation audit tasks" - when: - - run_audit or audit_only - - setup_audit + when: run_audit or audit_only or setup_audit tags: run_audit ansible.builtin.import_tasks: pre_remediation_audit.yml diff --git a/tasks/section_1/cis_1.2.2.x.yml b/tasks/section_1/cis_1.2.2.x.yml index 2ccb59f..379b92d 100644 --- a/tasks/section_1/cis_1.2.2.x.yml +++ b/tasks/section_1/cis_1.2.2.x.yml @@ -13,4 +13,4 @@ ansible.builtin.package: name: "*" state: latest - notify: Change_requires_reboot + notify: Set reboot required From b38e7d06eb757c2af71f5fd8482afb48a97162fb Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Mon, 16 Jun 2025 15:14:08 -0400 Subject: [PATCH 036/116] var fixes for 1.1.2.3.x and 1.1.2.4.x Signed-off-by: Frederick Witty --- tasks/pre_remediation_audit.yml | 2 +- tasks/prelim.yml | 16 +++++----------- tasks/section_1/cis_1.1.2.3.x.yml | 4 ++-- tasks/section_1/cis_1.1.2.4.x.yml | 4 ++-- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 61959fa..a2a37f1 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -46,7 +46,7 @@ remote_src: "{{ (audit_conf_source is contains('http')) | ternary(true, false) }}" extra_opts: "{{ (audit_conf_source is contains('github')) | ternary('--strip-components=1', []) }}" -- name: Pre Audit Setup | Check Goss is available +- name: Pre Audit Setup | Check goss is available when: run_audit block: - name: Pre Audit Setup | Check for goss file diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 2e0dd95..0e2b155 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -136,8 +136,7 @@ register: prelim_systemd_coredump - name: "PRELIM | PATCH | Setup crypto-policy" - when: - - rhel9cis_rule_1_6_1 + when: rhel9cis_rule_1_6_1 tags: - level1-server - level1-workstation @@ -185,15 +184,13 @@ grub2_path: /etc/grub2-efi.cfg - name: "PRELIM | AUDIT | Discover Gnome Desktop Environment" - tags: - - always + tags: always ansible.builtin.stat: path: /usr/share/gnome/gnome-version.xml register: prelim_gnome_present - name: "PRELIM | PATCH | Install dconf if gui installed" - when: - - rhel9cis_gui + when: rhel9cis_gui tags: - always ansible.builtin.package: @@ -251,9 +248,7 @@ state: touch - name: "PRELIM | PATCH | sshd_config.d/50-redhat.conf exists" - when: - - rhel9cis_rule_5_1_10 or - rhel9cis_rule_5_1_11 + when: rhel9cis_rule_5_1_10 or rhel9cis_rule_5_1_11 ansible.builtin.stat: path: /etc/ssh/sshd_config.d/50-redhat.conf register: discovered_sshd_50_redhat_file @@ -281,8 +276,7 @@ - name: "PRELIM | PATCH | Create journald config directory" when: - rhel9cis_syslog == 'journald' - - rhel9cis_rule_6_2_1_3 or - rhel9cis_rule_6_2_1_4 + - rhel9cis_rule_6_2_1_3 or rhel9cis_rule_6_2_1_4 tags: always ansible.builtin.file: path: /etc/systemd/journald.conf.d diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml index 998d1ba..635648d 100644 --- a/tasks/section_1/cis_1.1.2.3.x.yml +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -21,12 +21,12 @@ register: discovered_home_mount - name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | Absent" - when: discovered_dev_shm_mount is undefined + when: discovered_home_mount is undefined ansible.builtin.debug: msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" - name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | Present" - when: discovered_dev_shm_mount is undefined + when: discovered_home_mount is undefined ansible.builtin.import_tasks: file: warning_facts.yml diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml index e0afd4e..f89fe3f 100644 --- a/tasks/section_1/cis_1.1.2.4.x.yml +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -22,12 +22,12 @@ register: discovered_var_mount - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Absent" - when: discovered_dev_shm_mount is undefined + when: discovered_var_mount is undefined ansible.builtin.debug: msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Present" - when: discovered_dev_shm_mount is undefined + when: discovered_var_mount is undefined ansible.builtin.import_tasks: file: warning_facts.yml From 38a173546cce29a2eb779a40ff5f805c706eb74d Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Mon, 16 Jun 2025 16:49:36 -0400 Subject: [PATCH 037/116] Update auditd with check_mode Signed-off-by: Frederick Witty --- tasks/auditd.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/auditd.yml b/tasks/auditd.yml index 7b86b94..0fa0b32 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -7,6 +7,7 @@ - name: "POST | AUDITD | Set supported_syscalls variable" ansible.builtin.shell: ausyscall --dump | awk '{print $2}' changed_when: false + check_mode: false failed_when: discovered_auditd_syscalls.rc not in [ 0, 1 ] register: discovered_auditd_syscalls From acacb7a6bc6582a5b1e706a9002fa6d74d054fae Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Mon, 16 Jun 2025 17:18:08 -0400 Subject: [PATCH 038/116] QA Fixes Signed-off-by: Frederick Witty --- tasks/main.yml | 7 ++----- tasks/pre_remediation_audit.yml | 1 + tasks/prelim.yml | 6 ++---- tasks/section_1/cis_1.1.1.x.yml | 3 +-- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index fe50b10..e106120 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -17,9 +17,7 @@ success_msg: "This role is running a supported version of ansible {{ ansible_version.full }} >= {{ min_ansible_version }}" - name: "Setup rules if container" - when: - - ansible_connection == 'docker' or - ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] + when: ansible_connection == 'docker' or ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] tags: - container_discovery - always @@ -101,8 +99,7 @@ - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" # noqa name[template] ansible.builtin.assert: - that: - - not prelim_ansible_user_password_set.stdout.startswith("!") + that: not prelim_ansible_user_password_set.stdout.startswith("!") fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} is locked - It can break access" success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} user" diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index a2a37f1..80df209 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -1,4 +1,5 @@ --- + - name: Pre Audit Setup | Setup the LE audit when: setup_audit tags: setup_audit diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 0e2b155..3970db8 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -191,8 +191,7 @@ - name: "PRELIM | PATCH | Install dconf if gui installed" when: rhel9cis_gui - tags: - - always + tags: always ansible.builtin.package: name: dconf state: present @@ -201,8 +200,7 @@ when: - rhel9cis_rule_3_1_2 - not system_is_container - tags: - - always + tags: always block: - name: "PRELIM | AUDIT | Discover is wireless adapter on system" ansible.builtin.command: find /sys/class/net/*/ -type d -name wireless diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index adc094d..e67bb39 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -27,8 +27,7 @@ mode: 'go-rwx' - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | Disable cramfs" - when: - - not system_is_container + when: not system_is_container community.general.modprobe: name: cramfs state: absent From d2de2783a80afc1155b3232c8e78c6ac0665a147 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 19 Jun 2025 16:31:37 +0100 Subject: [PATCH 039/116] added ability to fetch audit and update title Signed-off-by: Mark Bolwell --- tasks/audit_only.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index d6f20ea..a33cb94 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -1,10 +1,17 @@ --- +- name: Audit_only | Fetch audit files + when: + - fetch_audit_output + - audit_only + ansible.builtin.import_tasks: + file: fetch_audit_output.yml + - name: Audit_only | Show Audit Summary when: audit_only ansible.builtin.debug: msg: "{{ audit_results.split('\n') }}" -- name: Audit_only | Stop Playbook Audit Only selected +- name: Audit_only | Stop task for host as audit_only selected when: audit_only - ansible.builtin.meta: end_play + ansible.builtin.meta: end_host From 379b18455426c5288f3e21e7434576fc9dd68082 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 19 Jun 2025 16:32:20 +0100 Subject: [PATCH 040/116] added changed_when to fix false warning errors Signed-off-by: Mark Bolwell --- tasks/fetch_audit_output.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/fetch_audit_output.yml b/tasks/fetch_audit_output.yml index 563b699..e440185 100644 --- a/tasks/fetch_audit_output.yml +++ b/tasks/fetch_audit_output.yml @@ -8,6 +8,7 @@ src: "{{ item }}" dest: "{{ audit_output_destination }}" flat: true + changed_when: true failed_when: false register: discovered_audit_fetch_state loop: From aaea8352de3a8b18fa48808dfa4d6cbd69522197 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 19 Jun 2025 16:33:29 +0100 Subject: [PATCH 041/116] updated Signed-off-by: Mark Bolwell --- Changelog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Changelog.md b/Changelog.md index 7542aa1..492516a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,11 @@ # Changes to rhel9CIS +## Based on CIS v2.0.0 + +Update to audit_only to allow fetching results +resolved false warning for fetch audit + ## 2.0.1 - Based on CIS v2.0.0 - Thanks to @polski-g several issues and improvements added From 82cc458d7a215c2b940228c59db3533ddc567b45 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 20 Jun 2025 11:32:31 +0100 Subject: [PATCH 042/116] Fix logic and notes for in crypto policy building Signed-off-by: Mark Bolwell --- Changelog.md | 1 + defaults/main.yml | 17 +++++++++-------- handlers/main.yml | 2 +- tasks/main.yml | 5 ++--- vars/main.yml | 6 ++++++ 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/Changelog.md b/Changelog.md index 492516a..573afd4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Update to audit_only to allow fetching results resolved false warning for fetch audit +Improved documentation and variable compilation for crypto policies ## 2.0.1 - Based on CIS v2.0.0 diff --git a/defaults/main.yml b/defaults/main.yml index cc49b0a..23312e5 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -12,7 +12,7 @@ os_check: true # Disruption is high ## Run tests that are considered higher risk and could have a system impact if not properly tested ## Default false -## Will be fine if clean new un configured build +## Will be fine if clean new un-configured build rhel9cis_disruption_high: false ## Switching on/off specific baseline sections @@ -37,6 +37,7 @@ rhel9cis_level_2: true # Create managed not custom local_facts files create_benchmark_facts: true ansible_facts_path: /etc/ansible/facts.d + ## Section 1.6 - Mandatory Access Control # This variable governs whether SELinux is disabled or not. If SELinux is NOT DISABLED by setting # 'rhel9cis_selinux_disable' to 'true', the 1.6 subsection will be executed. @@ -111,7 +112,7 @@ audit_conf_dest: "/opt" # Where the audit logs are stored audit_log_dir: '/opt' -## Ability to collect and take audit files moving to a centralised location +## Ability to collect and take audit files moving to a centralized location # This enables the collection of the files from the host fetch_audit_output: false @@ -238,7 +239,7 @@ rhel9cis_rule_1_8_8: true rhel9cis_rule_1_8_9: true rhel9cis_rule_1_8_10: true -# Section 2 rules are controlling Services (Special Purpose Services, and service clients) +# Section 2 rules are controling Services (Special Purpose Services, and service clients) ## Configure Server Services rhel9cis_rule_2_1_1: true rhel9cis_rule_2_1_2: true @@ -579,8 +580,8 @@ rhel9cis_crypto_policy: 'DEFAULT' ## Control 1.6 # This variable contains the value of the crypto policy module(combinations of policies and # sub-policies) to be allowed as default setting. Allowed options are defined in 'vars/main.yml' file, -# using 'rhel9cis_allowed_crypto_policies_modules' variable. -rhel9cis_crypto_policy_module: '' +# using those listed in the 'rhel9cis_allowed_crypto_policies_modules' variable. +rhel9cis_additional_crypto_policy_module: '' ## Controls: # - 1.7.1 - Ensure message of the day is configured properly @@ -816,7 +817,7 @@ rhel9cis_sshd_clientalivecountmax: 3 rhel9cis_sshd_clientaliveinterval: 15 ## Control 5.1.12 - disable forwarding -# By Default this will also disable x11 forwarding +# By Default this will also disablex11 forwarding # set 'yes' if x11 is required this can be changed to run in /etc/ssh/ssh_config.d/50-redhat.conf rhel9cis_sshd_x11forwarding: 'no' @@ -1046,14 +1047,14 @@ rhel9cis_bash_umask: '0027' # 0027 or more restrictive # These are discovered via logins.def if set true rhel9cis_discover_int_uid: true # This variable sets the minimum number from which to search for UID -# Note that the value will be dynamically overwritten if variable `discover_int_uid` has +# Note that the value will be dynamically overwritten if variable `rhel9cis_discover_int_uid` has # been set to `true`. min_int_uid: 1000 ### Controls: # - Ensure local interactive user home directories exist # - Ensure local interactive users own their home directories # This variable sets the maximum number at which the search stops for UID -# Note that the value will be dynamically overwritten if variable `discover_int_uid` has +# Note that the value will be dynamically overwritten if variable `rhel9cis_discover_int_uid` has # been set to `true`. max_int_uid: 65533 diff --git a/handlers/main.yml b/handlers/main.yml index 1a3b66e..4bc5a08 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -186,7 +186,7 @@ - name: Update Crypto Policy ansible.builtin.set_fact: - rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{% if rhel9cis_crypto_policy_module | length > 0 %}{{ rhel9cis_crypto_policy_module }}{% endif %}" + rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{{ rhel9cis_crypto_policy_module }}:{{ rhel9cis_additional_crypto_policy_module }}" notify: Set Crypto Policy - name: Set Crypto Policy diff --git a/tasks/main.yml b/tasks/main.yml index 43ec09c..9bfcc51 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -61,7 +61,7 @@ - crypto - NIST800-53R5_SC-6 ansible.builtin.assert: - that: rhel9cis_crypto_policy_module in rhel9cis_allowed_crypto_policies_modules + that: rhel9cis_additional_crypto_policy_module in rhel9cis_allowed_crypto_policies_modules fail_msg: "Crypto policy module is not a permitted version" success_msg: "Crypto policy module is a permitted version" @@ -132,9 +132,8 @@ - rule_5.4.2.4 block: - name: "Ensure root password is set" - ansible.builtin.shell: passwd -S root | grep -E "(Password set, SHA512 crypt|Password locked)" + ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)" changed_when: false - failed_when: prelim_root_passwd_set.rc not in [ 0, 1 ] register: prelim_root_passwd_set - name: "Ensure root password is set" diff --git a/vars/main.yml b/vars/main.yml index 5eed07c..9337d58 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -7,10 +7,16 @@ rhel9cis_allowed_crypto_policies: - 'FUTURE' - 'FIPS' +# Following is left blank for ability to build string +rhel9cis_crypto_policy_module: '' + +# Do not adjust these are recognized as part of the CIS benchmark and used during testing rhel9cis_allowed_crypto_policies_modules: + # Recognized by CIS as possible extra options - 'OSPP' - 'AD-SUPPORT' - 'AD-SUPPORT-LEGACY' + # The following are already included in 1.6.x controls - 'NO-SHA1' - 'NO-SSHCBC' - 'NO-SSHETM' From 9db79097f91ead59e1a1dfa6a038fffad99184d8 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 20 Jun 2025 12:14:14 +0100 Subject: [PATCH 043/116] fixed crypto logic Signed-off-by: Mark Bolwell --- handlers/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/handlers/main.yml b/handlers/main.yml index 4bc5a08..1894300 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -186,7 +186,7 @@ - name: Update Crypto Policy ansible.builtin.set_fact: - rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{{ rhel9cis_crypto_policy_module }}:{{ rhel9cis_additional_crypto_policy_module }}" + rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{{ rhel9cis_crypto_policy_module }}{% if rhel9cis_additional_crypto_policy_module | length > 0 %}:{{ rhel9cis_additional_crypto_policy_module }}{% endif %}" notify: Set Crypto Policy - name: Set Crypto Policy From 0ee2de5e208f902fd21e3c3a6053dfea1bc826c0 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Fri, 27 Jun 2025 12:04:29 -0400 Subject: [PATCH 044/116] Addresses #318 - Thank you @kodebach & @bgro Signed-off-by: Frederick Witty --- Changelog.md | 12 +++++++----- tasks/main.yml | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Changelog.md b/Changelog.md index 573afd4..52d568b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,11 +1,13 @@ # Changes to rhel9CIS +## 2.0.2 - Based on CIS v2.0.0 -## Based on CIS v2.0.0 - -Update to audit_only to allow fetching results -resolved false warning for fetch audit -Improved documentation and variable compilation for crypto policies +- Update to audit_only to allow fetching results +- resolved false warning for fetch audit +- fix root user check +- Improved documentation and variable compilation for crypto policies +- Addresses #318 - Thank you @kodebach & @bgro + - Improved logic for 5.2.4 to exclude rhel9cis_sudoers_exclude_nopasswd_list in pre-check tasks/main.yml ## 2.0.1 - Based on CIS v2.0.0 diff --git a/tasks/main.yml b/tasks/main.yml index f5a57db..9582bed 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -99,9 +99,9 @@ - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" # noqa name[template] ansible.builtin.assert: - that: not prelim_ansible_user_password_set.stdout.startswith("!") + that: (not prelim_ansible_user_password_set.stdout.startswith("!")) or (ansible_env.SUDO_USER in rhel9cis_sudoers_exclude_nopasswd_list) fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} is locked - It can break access" - success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} user" + success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} is not locked or included in the exception list for rule 5.2.4" - name: "Check authselect profile is selected" when: rhel9cis_allow_authselect_updates From 874890ee400eba6fc3b609796a685c1f7324cfa6 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Fri, 27 Jun 2025 12:06:18 -0400 Subject: [PATCH 045/116] Update site.yml hosts logic Signed-off-by: Frederick Witty --- site.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site.yml b/site.yml index f3f0fae..4386b04 100644 --- a/site.yml +++ b/site.yml @@ -1,7 +1,7 @@ --- - name: Apply ansible-lockdown hardening - hosts: all + hosts: "{{ hosts | default('all') }}" become: true roles: - role: "{{ playbook_dir }}" From 2142934148d33c6a1e7f71a9674f007847ae7fcb Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 1 Jul 2025 09:29:08 +0100 Subject: [PATCH 046/116] updated 6.3.3.5 Signed-off-by: Mark Bolwell --- templates/audit/99_auditd.rules.j2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 4d9c0d3..4fa4516 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -56,8 +56,10 @@ -w /etc/issue -p wa -k system-locale -w /etc/issue.net -p wa -k system-locale -w /etc/hosts -p wa -k system-locale +-w /etc/hostname -p wa -k system-locale -w /etc/sysconfig/network -p wa -k system-locale -w /etc/sysconfig/network-scripts -p wa -k system-locale +-w /etc/NetworkManager -p wa -k system-locale {% endif %} {% if rhel9cis_rule_6_3_3_6 %} {% for proc in discovered_priv_procs.stdout_lines -%} From b8ed2dfdac24d7526cdfbe1db0f58c75491356d4 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 1 Jul 2025 09:37:25 +0100 Subject: [PATCH 047/116] updated Signed-off-by: Mark Bolwell --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 52d568b..8ca9c4f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ - Improved documentation and variable compilation for crypto policies - Addresses #318 - Thank you @kodebach & @bgro - Improved logic for 5.2.4 to exclude rhel9cis_sudoers_exclude_nopasswd_list in pre-check tasks/main.yml +- rule_6.3.3.5 updated for missing checks ## 2.0.1 - Based on CIS v2.0.0 From 0a56b16d32259a4d09288df2f6dce90e49a681b3 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 4 Jul 2025 11:32:56 +0100 Subject: [PATCH 048/116] updated as per public fix #360 Signed-off-by: Mark Bolwell --- tasks/auditd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/auditd.yml b/tasks/auditd.yml index 0fa0b32..9ada459 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -25,7 +25,7 @@ dest: /etc/audit/rules.d/99_auditd.rules owner: root group: root - mode: 'u-x,go-wx' + mode: 'u-x,g-wx,o-rwx' diff: "{{ discovered_auditd_rules_file.stat.exists }}" # Only run diff if not a new file register: discovered_auditd_rules_template_updated notify: From 3778d6fb620e9f289e61fb693e59bdd305e8cb57 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 4 Jul 2025 11:34:53 +0100 Subject: [PATCH 049/116] improvement updated with public #361 Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.4.2.x.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index 37a4e11..9a93947 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -135,6 +135,22 @@ ansible.builtin.set_fact: root_paths: "{{ discovered_root_paths.stdout }}" + - name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Check for presence of non-dirs" + ansible.builtin.stat: + path: "{{ item }}" + loop: "{{ discovered_root_paths_split.stdout_lines }}" + register: paths_stat + + - name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Create dirs for some paths that are not dirs" + ansible.builtin.file: + path: "{{ item.item }}" + state: directory + owner: root + group: root + mode: 'go-w' + loop: "{{ paths_stat.results }}" + when: not item.stat.exists + - name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Check for empty dirs" when: discovered_root_paths is defined ansible.builtin.shell: 'echo {{ root_paths }} | grep -q "::" && echo "roots path contains a empty directory (::)"' From ef2c4d4ddbcdb838cb8a163a2e4e0ff981aa31aa Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 4 Aug 2025 10:15:48 +0100 Subject: [PATCH 050/116] Updated audit file permissions when running audit thansk to @steve-hayes Signed-off-by: Mark Bolwell --- tasks/post_remediation_audit.yml | 11 +---------- tasks/pre_remediation_audit.yml | 4 ++-- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 68e7035..357a23f 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -1,22 +1,13 @@ --- - name: Post Audit | Run post_remediation {{ benchmark }} audit # noqa name[template] - ansible.builtin.command: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" + ansible.builtin.shell: "umask 0022 && {{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" AUDIT_FILE: goss.yml -- name: Post Audit | ensure audit files readable by users - ansible.builtin.file: - path: "{{ item }}" - mode: '0644' - state: file - loop: - - "{{ post_audit_outfile }}" - - "{{ pre_audit_outfile }}" - - name: Post Audit | Capture audit data if json format when: audit_format == "json" block: diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 80df209..ff6aad0 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -47,7 +47,7 @@ remote_src: "{{ (audit_conf_source is contains('http')) | ternary(true, false) }}" extra_opts: "{{ (audit_conf_source is contains('github')) | ternary('--strip-components=1', []) }}" -- name: Pre Audit Setup | Check goss is available +- name: Pre Audit Setup | Check Goss is available when: run_audit block: - name: Pre Audit Setup | Check for goss file @@ -71,7 +71,7 @@ mode: 'go-rwx' - name: Pre Audit | Run pre_remediation audit {{ benchmark }} # noqa name[template] - ansible.builtin.command: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] + ansible.builtin.shell: "umask 0022 && {{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" From 62095f75fe9f97b35d0a584286c3b75cee9e204b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 14 Aug 2025 16:14:47 +0100 Subject: [PATCH 051/116] updated as per public PR #350 Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.2.3.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_6/cis_6.2.3.x.yml b/tasks/section_6/cis_6.2.3.x.yml index 9d26acf..eaa3bd1 100644 --- a/tasks/section_6/cis_6.2.3.x.yml +++ b/tasks/section_6/cis_6.2.3.x.yml @@ -131,7 +131,7 @@ *.=warning;*.=err -/var/log/warn *.crit /var/log/warn *.*;mail.none;news.none /var/log/messages - insertafter: '#### RULES ####' + insertbefore: '# ### sample forwarding rule ###' notify: Restart rsyslog - name: "6.2.3.5 | PATCH | Ensure logging is configured | Local log settings" From 73320db603a2878c6567f1ce15fbe40c4661c473 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 14 Aug 2025 16:17:45 +0100 Subject: [PATCH 052/116] dont not run section 1.8 if not gdm PR #364 from public Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 ++ tasks/section_1/main.yml | 1 + 2 files changed, 3 insertions(+) diff --git a/defaults/main.yml b/defaults/main.yml index 23312e5..bf40e8f 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -592,6 +592,8 @@ rhel9cis_warning_banner: Authorized users only. All activity may be monitored an # End Banner ## Control 1.8.x - Settings for GDM +# do not run Control 1.8.x if using a display manager different than gdm +rhel9cis_display_manager: "gdm" ## 1.8 GDM graphical interface rhel9cis_gui: "{{ prelim_gnome_present.stat.exists | default(false) }}" # This variable specifies the GNOME configuration database file to which configurations are written. diff --git a/tasks/section_1/main.yml b/tasks/section_1/main.yml index 5d99f48..8c1f39b 100644 --- a/tasks/section_1/main.yml +++ b/tasks/section_1/main.yml @@ -61,5 +61,6 @@ file: cis_1.7.x.yml - name: "SECTION | 1.8 | Gnome Display Manager" + when: rhel9cis_display_manager == 'gdm' ansible.builtin.import_tasks: file: cis_1.8.x.yml From 625e4041c1d68735b16abbf2575a0b9086527fb2 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 14 Aug 2025 16:20:51 +0100 Subject: [PATCH 053/116] update logic for 5.2.4 public PR #371 Signed-off-by: Mark Bolwell --- tasks/main.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index 7912aca..c778d5f 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -91,11 +91,14 @@ block: - name: "Check password set for {{ ansible_env.SUDO_USER }} | Assert local password set" # noqa name[template] ansible.builtin.assert: - that: - - prelim_ansible_user_password_set.stdout | length != 0 - - prelim_ansible_user_password_set.stdout != "!!" - fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} has no password set - It can break access" - success_msg: "You have a password set for the {{ ansible_env.SUDO_USER }} user" + that: | + ( + ((prelim_ansible_user_password_set.stdout | length != 0) and (prelim_ansible_user_password_set.stdout != "!!" )) + or + (ansible_env.SUDO_USER in rhel9cis_sudoers_exclude_nopasswd_list) + ) + fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} has no password set or or the user is not included in the exception list for rule 5.2.4 - It can break access" + success_msg: "You have a password set for the {{ ansible_env.SUDO_USER }} user or the user is included in the exception list for rule 5.2.4" - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" # noqa name[template] ansible.builtin.assert: From 55917c8daad28c6767331ab0b61d362d70142dae Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 14 Aug 2025 16:27:41 +0100 Subject: [PATCH 054/116] udpated pre-commit hooks version Signed-off-by: Mark Bolwell --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2561fb5..b4f6d0c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ ci: repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: # Safety - id: detect-aws-credentials From 4b302f97f9067c35f04ae578314db674dc9e4577 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 14 Aug 2025 16:50:41 +0100 Subject: [PATCH 055/116] fixed compability pre 2.14 thanks to public PR #380 Signed-off-by: Mark Bolwell --- handlers/main.yml | 2 +- tasks/section_6/cis_6.1.x.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/handlers/main.yml b/handlers/main.yml index 71f5554..c6de8f3 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -263,7 +263,7 @@ listen: Restart auditd - name: Start auditd process - ansible.builtin.systemd_service: + ansible.builtin.systemd: name: auditd state: started listen: Restart auditd diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 1db531b..a29118a 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -91,13 +91,13 @@ - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked | aide service" when: rhel9cis_aide_scan == "timer" - ansible.builtin.systemd_service: + ansible.builtin.systemd: name: aidecheck.service enabled: true - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked | aide service" when: rhel9cis_aide_scan == "timer" - ansible.builtin.systemd_service: + ansible.builtin.systemd: name: aidecheck.timer state: started enabled: true From 95ed2ff03d520c90d5f40ebf61b71b85e05fdd52 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 14 Aug 2025 17:09:58 +0100 Subject: [PATCH 056/116] changed to import task public PR 377 Signed-off-by: Mark Bolwell --- Changelog.md | 15 +++++++++++++++ tasks/section_1/main.yml | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index b6db646..931df92 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,20 @@ # Changes to rhel9CIS +## 2.0.3 - Based on CIS v2.0.0 + +- Thanks to @numericillustration + - Public PR 380 + - systemd_service rolled back to systemd for < ansible 2.14 +- Thanks to @bgro and @Kodebach + - Public PR 371 + - updated to user sudo check 5.2.4 +- Thanks to @polski-g + - Public PR 364 + - gdm section 1.8 improvements +- Thanks to @chrispipo + - Public PR 350 + - change insert before for rsyslog setting + ## 2.0.2 - Based on CIS v2.0.0 - Update to audit_only to allow fetching results diff --git a/tasks/section_1/main.yml b/tasks/section_1/main.yml index 8c1f39b..fff557b 100644 --- a/tasks/section_1/main.yml +++ b/tasks/section_1/main.yml @@ -41,7 +41,7 @@ file: cis_1.2.2.x.yml - name: "SECTION | 1.3.1 | Configure SELinux" - ansible.builtin.include_tasks: + ansible.builtin.import_tasks: file: cis_1.3.1.x.yml - name: "SECTION | 1.4 | Configure Bootloader" From 55c7fa6dd5eef06d4f200c7ff6ff9b9363225efe Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 14 Aug 2025 17:12:56 +0100 Subject: [PATCH 057/116] added password of different LC public issue 372 Signed-off-by: Mark Bolwell --- tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/main.yml b/tasks/main.yml index c778d5f..ed2af41 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -132,7 +132,7 @@ - rule_5.4.2.4 block: - name: "Ensure root password is set" - ansible.builtin.shell: passwd -S root | grep -E "(Password set, SHA512 crypt|Password locked)" + ansible.builtin.shell: LC_ALL=C passwd -S root | grep -E "(Password set, SHA512 crypt|Password locked)" changed_when: false failed_when: prelim_root_passwd_set.rc not in [ 0, 1 ] register: prelim_root_passwd_set From f1e50bdc4c2a9f4007c28f94d423d9ead5630229 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 14 Aug 2025 17:15:35 +0100 Subject: [PATCH 058/116] updated Signed-off-by: Mark Bolwell --- Changelog.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Changelog.md b/Changelog.md index 931df92..89a54c3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -14,6 +14,12 @@ - Thanks to @chrispipo - Public PR 350 - change insert before for rsyslog setting +- Thanks to @thesmilinglord + - public issue 377 + - change 1.3 from include task to import for tagging +- Thanks to @Fredouye + - public issue 372 + - allow password with different locale ## 2.0.2 - Based on CIS v2.0.0 From eafee7e040cadbe59728e8b472f7d20673f2a32e Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 14 Aug 2025 17:19:53 +0100 Subject: [PATCH 059/116] Added typo updates thanks to @DianaMariaDDM Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.2.6.x.yml | 2 +- tasks/section_1/cis_1.1.2.7.x.yml | 2 +- tasks/section_3/cis_3.3.x.yml | 4 ++-- tasks/section_5/cis_5.4.2.x.yml | 2 +- tasks/section_6/cis_6.3.4.x.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tasks/section_1/cis_1.1.2.6.x.yml b/tasks/section_1/cis_1.1.2.6.x.yml index 765de3d..b27e4cc 100644 --- a/tasks/section_1/cis_1.1.2.6.x.yml +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -1,6 +1,6 @@ --- -- name: "1/.1 | PATCH | Ensure /var/log is a separate partition" +- name: "1.1.2.6.1 | PATCH | Ensure /var/log is a separate partition" when: - rhel9cis_rule_1_1_2_6_1 - required_mount not in prelim_mount_names diff --git a/tasks/section_1/cis_1.1.2.7.x.yml b/tasks/section_1/cis_1.1.2.7.x.yml index 2dc5939..b4513dd 100644 --- a/tasks/section_1/cis_1.1.2.7.x.yml +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -1,6 +1,6 @@ --- -- name: "1/.1 | PATCH | Ensure /var/log/audit is a separate partition" +- name: "1.1.2.7.1 | PATCH | Ensure /var/log/audit is a separate partition" when: - rhel9cis_rule_1_1_2_7_1 - required_mount not in prelim_mount_names diff --git a/tasks/section_3/cis_3.3.x.yml b/tasks/section_3/cis_3.3.x.yml index 123928e..0281f12 100644 --- a/tasks/section_3/cis_3.3.x.yml +++ b/tasks/section_3/cis_3.3.x.yml @@ -240,12 +240,12 @@ - rule_3.3.9 - NIST800-53R5_AU-3 block: - - name: "3.3.4 | PATCH | Ensure suspicious packets are logged | Set Fact" + - name: "3.3.9 | PATCH | Ensure suspicious packets are logged | Set Fact" ansible.builtin.set_fact: rhel9cis_sysctl_update: true rhel9cis_flush_ipv4_route: true - - name: "3.3.4 | PATCH | Ensure suspicious packets are logged" + - name: "3.3.9 | PATCH | Ensure suspicious packets are logged" ansible.builtin.debug: msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index 9a93947..b3dd7d9 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -61,7 +61,7 @@ - level1-server - level1-workstation - patch - - rule_5.4.2.2 + - rule_5.4.2.3 - user - system - NIST800-53R5_CM-1 diff --git a/tasks/section_6/cis_6.3.4.x.yml b/tasks/section_6/cis_6.3.4.x.yml index 74de70a..b044abc 100644 --- a/tasks/section_6/cis_6.3.4.x.yml +++ b/tasks/section_6/cis_6.3.4.x.yml @@ -27,9 +27,9 @@ - level2-workstation - patch - auditd - - rule_6.3.4.1 - rule_6.3.4.2 - rule_6.3.4.3 + - rule_6.3.4.4 - NIST800-53R5_AU-3 ansible.builtin.file: path: "{{ prelim_auditd_logfile.stdout }}" From 811b70612ea8c7f4c8527b962c130eb634bbe1b3 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 14 Aug 2025 17:25:37 +0100 Subject: [PATCH 060/116] udpated Signed-off-by: Mark Bolwell --- Changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index 89a54c3..b25de77 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,9 @@ - Thanks to @bgro and @Kodebach - Public PR 371 - updated to user sudo check 5.2.4 +- Thanks to @DianaMariaDDM + - Public PR 367 + - updated several typos - Thanks to @polski-g - Public PR 364 - gdm section 1.8 improvements From 67c574d8a9a1a35fe53a72b8dad3084f23ee9e2e Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Wed, 10 Sep 2025 12:57:50 -0400 Subject: [PATCH 061/116] Updates from Public Signed-off-by: Frederick Witty --- Changelog.md | 7 +++++++ defaults/main.yml | 4 +++- tasks/main.yml | 4 ++-- tasks/prelim.yml | 2 +- tasks/section_1/cis_1.4.x.yml | 1 + tasks/section_1/cis_1.6.x.yml | 13 ++++++++++--- tasks/section_4/cis_4.3.x.yml | 2 +- tasks/section_5/cis_5.1.x.yml | 3 +++ tasks/section_5/cis_5.4.1.x.yml | 3 ++- tasks/section_5/cis_5.4.2.x.yml | 4 ++-- 10 files changed, 32 insertions(+), 11 deletions(-) diff --git a/Changelog.md b/Changelog.md index b25de77..c5870e9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,13 @@ ## 2.0.3 - Based on CIS v2.0.0 +- Thank you @fragglexarmy + - addressed Public issue 387 +- Addressed Public issue 382 to improve regex logic on 5.4.2.4 +- Improvement on crypto policy managed controls with var logic +- Thanks to @polski-g + - addressed issue 384 +- update command to shell module on tasks - Thanks to @numericillustration - Public PR 380 - systemd_service rolled back to systemd for < ansible 2.14 diff --git a/defaults/main.yml b/defaults/main.yml index bf40e8f..866a3f1 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -569,7 +569,9 @@ rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' # pr # This variable governs whether a bootloader password should be set in '/boot/grub2/user.cfg' file. rhel9cis_set_boot_pass: true -## Control 1.6 +## Controls 1.6.x and Controls 5.1.x +# This variable governs if current Ansible role should manage system-wide crypto policy. +rhel9cis_crypto_policy_ansiblemanaged: true # This variable contains the value to be set as the system-wide crypto policy. Current rule enforces NOT USING # 'LEGACY' value(as it is less secure, it just ensures compatibility with legacy systems), therefore # possible values for this variable are, as explained by RedHat docs: diff --git a/tasks/main.yml b/tasks/main.yml index ed2af41..da19416 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -52,7 +52,7 @@ - name: "Check crypto-policy module input" when: - - rhel9cis_rule_1_6_1 + - rhel9cis_crypto_policy_ansiblemanaged - rhel9cis_crypto_policy_module | length > 0 tags: - rule_1.6.1 @@ -132,7 +132,7 @@ - rule_5.4.2.4 block: - name: "Ensure root password is set" - ansible.builtin.shell: LC_ALL=C passwd -S root | grep -E "(Password set, SHA512 crypt|Password locked)" + ansible.builtin.shell: LC_ALL=C passwd -S root | grep -E "(Password set|Password locked)" changed_when: false failed_when: prelim_root_passwd_set.rc not in [ 0, 1 ] register: prelim_root_passwd_set diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 3e2d4cd..c39448b 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -136,7 +136,7 @@ register: prelim_systemd_coredump - name: "PRELIM | PATCH | Setup crypto-policy" - when: rhel9cis_rule_1_6_1 + when: rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index c6c3aac..5969dff 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -52,6 +52,7 @@ - name: "1.4.2 | AUDIT | Ensure permissions on bootloader config are configured | efi based system | capture current state" ansible.builtin.shell: grep "^[^#;]" /etc/fstab | grep '/boot/efi' | awk -F" " '{print $4}' changed_when: false + check_mode: false register: discovered_efi_fstab - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | efi based system | Build Options" diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml index c418324..6662303 100644 --- a/tasks/section_1/cis_1.6.x.yml +++ b/tasks/section_1/cis_1.6.x.yml @@ -1,7 +1,9 @@ --- - name: "1.6.1 | AUDIT | Ensure system-wide crypto policy is not legacy" - when: rhel9cis_rule_1_6_1 + when: + - rhel9cis_rule_1_6_1 + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation @@ -21,12 +23,14 @@ tags: - level1-server - level1-workstation + - sshd - automated - patch - rule_1.6.2 - NIST800-53R5_SC-8 - NIST800-53R5_IA-5 - - NIST800-53R5_AC-17- NIST800-53R5_SC-6 + - NIST800-53R5_AC-17 + - NIST800-53R5_SC-6 ansible.builtin.lineinfile: path: /etc/sysconfig/sshd regexp: ^CRYPTO_POLICY\s*= @@ -37,6 +41,7 @@ when: - rhel9cis_rule_1_6_3 - "'NO-SHA1' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation @@ -67,6 +72,7 @@ when: - rhel9cis_rule_1_6_4 - "'NO-WEAKMAC' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation @@ -76,7 +82,6 @@ - rule_1.6.4 - NIST800-53R5_SC-6 block: - - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | Add submodule exclusion" ansible.builtin.template: src: etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 @@ -98,6 +103,7 @@ when: - rhel9cis_rule_1_6_5 - "'NO-SSHCBC' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation @@ -128,6 +134,7 @@ when: - rhel9cis_rule_1_6_6 - "'NO-SSHWEAKCIPHERS' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation diff --git a/tasks/section_4/cis_4.3.x.yml b/tasks/section_4/cis_4.3.x.yml index 4e23998..4398df2 100644 --- a/tasks/section_4/cis_4.3.x.yml +++ b/tasks/section_4/cis_4.3.x.yml @@ -81,7 +81,7 @@ register: discovered_nftables_inconnectionrule - name: "4.3.2 | AUDIT | Ensure nftables established connections are configured | Gather outbound connection rules" - ansible.builtin.command: nft list ruleset | awk '/hook output/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state' + ansible.builtin.shell: nft list ruleset | awk '/hook output/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state' changed_when: false failed_when: false register: discovered_nftables_outconnectionrule diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index 3fd366c..42ca036 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -80,6 +80,7 @@ when: - rhel9cis_rule_5_1_4 - "'NO-SSHWEAKCIPHERS' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation @@ -108,6 +109,7 @@ when: - rhel9cis_rule_5_1_5 - "'NO-SHA1' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation @@ -136,6 +138,7 @@ when: - rhel9cis_rule_5_1_6 - "'NO-SSHWEAKMACS' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index 7fcfb0b..ea6eb11 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -24,6 +24,7 @@ ansible.builtin.shell: "awk -F: '(/^[^:]+:[^!*]/ && ($5> {{ rhel9cis_pass_max_days }} || $5< {{ rhel9cis_pass_max_days }} || $5 == -1)){print $1}' /etc/shadow" changed_when: false failed_when: false + check_mode: false register: discovered_max_days - name: "5.4.1.1 | PATCH | Ensure password expiration is 365 days or less | Set existing users PASS_MAX_DAYS" @@ -64,7 +65,7 @@ - rhel9cis_force_user_mindays ansible.builtin.user: name: "{{ item }}" - password_expire_max: "{{ rhel9cis_pass_min_days }}" + password_expire_min: "{{ rhel9cis_pass_min_days }}" loop: "{{ discovered_min_days.stdout_lines }}" - name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured" diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index b3dd7d9..b291cc2 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -139,7 +139,7 @@ ansible.builtin.stat: path: "{{ item }}" loop: "{{ discovered_root_paths_split.stdout_lines }}" - register: paths_stat + register: discovered_root_paths_stat - name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Create dirs for some paths that are not dirs" ansible.builtin.file: @@ -148,7 +148,7 @@ owner: root group: root mode: 'go-w' - loop: "{{ paths_stat.results }}" + loop: "{{ discovered_root_paths_stat.results }}" when: not item.stat.exists - name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Check for empty dirs" From d927b3006da56383b7cc3c095efcfa1ffb1e4a46 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Thu, 11 Sep 2025 16:05:24 -0400 Subject: [PATCH 062/116] linting clean up Signed-off-by: Frederick Witty --- tasks/prelim.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index c39448b..bf03d58 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -1,7 +1,7 @@ --- -# Preliminary tasks that should always be run -# List users in order to look files inside each home directory +# Preliminary tasks that should always run +# List users in order to look up files inside each home directory - name: "PRELIM | Include audit specific variables" when: run_audit or audit_only or setup_audit @@ -166,6 +166,7 @@ current_crypto_module: "{{ prelim_system_wide_crypto_policy.stdout.split(':')[1] }}" - name: "PRELIM | AUDIT | Set facts based on boot type" + tags: always block: - name: "PRELIM | AUDIT | Check whether machine is UEFI-based" ansible.builtin.stat: @@ -353,7 +354,6 @@ prelim_max_int_uid: "{{ prelim_uid_max_id.stdout | default(max_int_uid) }}" - name: "PRELIM | AUDIT | Gather the package facts after prelim" - tags: - - always + tags: always ansible.builtin.package_facts: manager: auto From 9a113ea4a864ef40a287036ac82d5af2563be70c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 30 Sep 2025 14:17:08 +0100 Subject: [PATCH 063/116] fix pre-commit var naming for authselect Signed-off-by: Mark Bolwell --- tasks/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index da19416..6c5a3f3 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -118,8 +118,8 @@ - name: "Check authselect profile is selected | Check current profile" ansible.builtin.command: authselect list changed_when: false - failed_when: prelim_authselect_current_profile.rc not in [ 0, 1 ] - register: prelim_authselect_current_profile + failed_when: prelim_authselect_profile_list.rc not in [ 0, 1 ] + register: prelim_authselect_profile_list - name: "Ensure root password is set" when: rhel9cis_rule_5_4_2_4 From 5dd64ebdb86bbdbb352e837aed67536e0eb1eb78 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 30 Sep 2025 14:20:10 +0100 Subject: [PATCH 064/116] max concurrent options and default added Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 ++ tasks/LE_audit_setup.yml | 1 - tasks/post_remediation_audit.yml | 2 +- tasks/pre_remediation_audit.yml | 3 ++- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 866a3f1..0110b42 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -75,6 +75,8 @@ setup_audit: false run_audit: false # Run heavy tests - some tests can have more impact on a system enabling these can have greater impact on a system audit_run_heavy_tests: true +# Ability to limit the number of concurrent processes used by goss (default 50) +audit_max_concurrent: 50 ## Only run Audit do not remediate audit_only: false diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index 53293e7..d784dc1 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -1,5 +1,4 @@ --- - - name: Pre Audit Setup | Set audit package name block: - name: Pre Audit Setup | Set audit package name | 64bit diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 357a23f..5e9419c 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -1,7 +1,7 @@ --- - name: Post Audit | Run post_remediation {{ benchmark }} audit # noqa name[template] - ansible.builtin.shell: "umask 0022 && {{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] + ansible.builtin.shell: "umask 0022 && {{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -m {{ audit_max_concurrent }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index ff6aad0..dd9efb4 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -58,6 +58,7 @@ - name: Pre Audit Setup | If audit ensure goss is available when: not prelim_goss_available.stat.exists ansible.builtin.assert: + that: prelim_goss_available['stat']['exists'] == true msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}" - name: Pre Audit Setup | Copy ansible default vars values to test audit @@ -71,7 +72,7 @@ mode: 'go-rwx' - name: Pre Audit | Run pre_remediation audit {{ benchmark }} # noqa name[template] - ansible.builtin.shell: "umask 0022 && {{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] + ansible.builtin.shell: "umask 0022 && {{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -m {{ audit_max_concurrent }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" From 3c3bdaeb38826b4933252c0a116db28b07bf6ef0 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 30 Sep 2025 14:36:15 +0100 Subject: [PATCH 065/116] using benchmark_version variable Signed-off-by: Mark Bolwell --- templates/ansible_vars_goss.yml.j2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index 7cb906b..e709a10 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -1,7 +1,7 @@ --- -# Enable logrunning potential resource intensive tests +# Enable long running potential resource intensive tests run_heavy_tests: {{ audit_run_heavy_tests }} # Extend default command timeout for longer running tests @@ -37,7 +37,7 @@ rhel9cis_legacy_boot: {{ rhel9cis_legacy_boot }} ## Benchmark name used by auditing control role # The audit variable found at the base ## metadata for Audit benchmark -benchmark_version: 'v2.0.0' +benchmark_version: {{ benchmark_version }} benchmark: RHEL9-CIS From caffb1467131f8949c2bb7b79c73822b3360b8bc Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 30 Sep 2025 14:38:45 +0100 Subject: [PATCH 066/116] applied latest fix from public #386 thansk to @polski-g Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.3.2.x.yml | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index 5917019..6e1919c 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -91,9 +91,15 @@ insertafter: "{{ item.after | default(omit) }}" line: "{{ item.line }}" loop: - - { regexp: auth\s*required\s*pam_faillock.so preauth, after: auth\s*required\s*pam_env.so, line: "auth required pam_faillock.so preauth silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } - - { regexp: auth\s*required\s*pam_faillock.so authfail, before: auth\s*required\s*pam_deny.so, line: "auth required pam_faillock.so authfail silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } - - { regexp: account\s*required\s*pam_faillock.so, before: account\s*required\s*pam_unix.so, line: "account required pam_faillock.so" } + - regexp: "auth\\s+required\\s+pam_faillock.so\\s+preauth" + after: "auth\\s+required\\s+pam_env.so" # yamllint disable-line rule:colons + line: "auth required pam_faillock.so preauth silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" # yamllint disable-line rule:colons + - regexp: "auth\\s+required\\s+pam_faillock.so\\s+authfail" + before: "auth\\s+required\\s+pam_deny.so" + line: "auth required pam_faillock.so authfail silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" # yamllint disable-line rule:colons + - regexp: "account\\s+required\\s+pam_faillock.so" + before: "account\\s+required\\s+pam_unix.so" + line: "account required pam_faillock.so" # yamllint disable-line rule:colons - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add lines password-auth" when: not rhel9cis_allow_authselect_updates @@ -104,9 +110,15 @@ insertafter: "{{ item.after | default(omit) }}" line: "{{ item.line }}" loop: - - { regexp: auth\s*required\s*pam_faillock.so preauth, after: auth\s*required\s*pam_env.so, line: "auth required pam_faillock.so preauth silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } - - { regexp: auth\s*required\s*pam_faillock.so authfail, before: auth\s*required\s*pam_deny.so, line: "auth required pam_faillock.so authfail silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } - - { regexp: account\s*required\s*pam_faillock.so, before: account\s*required\s*pam_unix.so, line: "account required pam_faillock.so" } + - regexp: "auth\\s+required\\s+pam_faillock.so\\s+preauth" + after: "auth\\s+required\\s+pam_env.so" # yamllint disable-line rule:colons + line: "auth required pam_faillock.so preauth silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" # yamllint disable-line rule:colons + - regexp: "auth\\s+required\\s+pam_faillock.so\\s+authfail" + before: "auth\\s+required\\s+pam_deny.so" + line: "auth required pam_faillock.so authfail silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" # yamllint disable-line rule:colons + - regexp: "account\\s+required\\s+pam_faillock.so" + before: "account\\s+required\\s+pam_unix.so" + line: "account required pam_faillock.so" # yamllint disable-line rule:colons - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled" when: From 7769bec99eab92409fce0ff3557dc60fa4565948 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 30 Sep 2025 14:44:57 +0100 Subject: [PATCH 067/116] Added section5 subsections public #390 thanks to @polski-g Signed-off-by: Mark Bolwell --- defaults/main.yml | 6 ++++ tasks/section_5/main.yml | 62 +++++++++++++++++++++++----------------- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 0110b42..0c95ee9 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -19,11 +19,17 @@ rhel9cis_disruption_high: false # These variables govern whether the tasks of a particular section are to be executed when running the role. # E.g: If you want to execute the tasks of Section 1 you should set the "_section1" variable to true. # If you do not want the tasks from that section to get executed you simply set the variable to "false". +# Some sections support sub-section modularization. The super-section and sub-section must both be true +# for the sub-section to execute. rhel9cis_section1: true rhel9cis_section2: true rhel9cis_section3: true rhel9cis_section4: true rhel9cis_section5: true +rhel9cis_section5_1: true +rhel9cis_section5_2: true +rhel9cis_section5_3: true +rhel9cis_section5_4: true rhel9cis_section6: true rhel9cis_section7: true diff --git a/tasks/section_5/main.yml b/tasks/section_5/main.yml index ae908ac..3d4db89 100644 --- a/tasks/section_5/main.yml +++ b/tasks/section_5/main.yml @@ -5,45 +5,53 @@ - name: "SECTION | 5.1 | Configure SSH Server" when: - "'openssh-server' in ansible_facts.packages" + - rhel9cis_section5_1 ansible.builtin.import_tasks: file: cis_5.1.x.yml - name: "SECTION | 5.2 | Configure privilege escalation" + when: rhel9cis_section5_2 ansible.builtin.import_tasks: file: cis_5.2.x.yml -- name: "SECTION | 5.3.1.x | Configure PAM software packages" - ansible.builtin.import_tasks: - file: cis_5.3.1.x.yml +- name: "SECTION | 5.3" + when: rhel9cis_section5_3 + block: + - name: "SECTION | 5.3.1.x | Configure PAM software packages" + ansible.builtin.import_tasks: + file: cis_5.3.1.x.yml -- name: "SECTION | 5.3.2.x | Configure authselect" - ansible.builtin.import_tasks: - file: cis_5.3.2.x.yml + - name: "SECTION | 5.3.2.x | Configure authselect" + ansible.builtin.import_tasks: + file: cis_5.3.2.x.yml -- name: "SECTION | 5.3.3.1.x | Configure pam_faillock module" - ansible.builtin.import_tasks: - file: cis_5.3.3.1.x.yml + - name: "SECTION | 5.3.3.1.x | Configure pam_faillock module" + ansible.builtin.import_tasks: + file: cis_5.3.3.1.x.yml -- name: "SECTION | 5.3.3.2.x | Configure pam_pwquality module" - ansible.builtin.import_tasks: - file: cis_5.3.3.2.x.yml + - name: "SECTION | 5.3.3.2.x | Configure pam_pwquality module" + ansible.builtin.import_tasks: + file: cis_5.3.3.2.x.yml -- name: "SECTION | 5.3.3.3.x | Configure pam_pwhistory module" - ansible.builtin.import_tasks: - file: cis_5.3.3.3.x.yml + - name: "SECTION | 5.3.3.3.x | Configure pam_pwhistory module" + ansible.builtin.import_tasks: + file: cis_5.3.3.3.x.yml -- name: "SECTION | 5.3.3.4.x | Configure pam_unix module" - ansible.builtin.import_tasks: - file: cis_5.3.3.4.x.yml + - name: "SECTION | 5.3.3.4.x | Configure pam_unix module" + ansible.builtin.import_tasks: + file: cis_5.3.3.4.x.yml -- name: "SECTION | 5.4.1.x | Configure shadow password suite parameters" - ansible.builtin.import_tasks: - file: cis_5.4.1.x.yml +- name: "SECTION | 5.4" + when: rhel9cis_section5_4 + block: + - name: "SECTION | 5.4.1.x | Configure shadow password suite parameters" + ansible.builtin.import_tasks: + file: cis_5.4.1.x.yml -- name: "SECTION | 5.4.2.x | Configure root and system accounts and environment" - ansible.builtin.import_tasks: - file: cis_5.4.2.x.yml + - name: "SECTION | 5.4.2.x | Configure root and system accounts and environment" + ansible.builtin.import_tasks: + file: cis_5.4.2.x.yml -- name: "SECTION | 5.4.3.x | Configure user default environment" - ansible.builtin.import_tasks: - file: cis_5.4.3.x.yml + - name: "SECTION | 5.4.3.x | Configure user default environment" + ansible.builtin.import_tasks: + file: cis_5.4.3.x.yml From f09cd1dcc6e989b718dd62e834e4659cb6080084 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 30 Sep 2025 14:52:29 +0100 Subject: [PATCH 068/116] updated ansible lint version Signed-off-by: Mark Bolwell --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b4f6d0c..a1a002d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -48,7 +48,7 @@ repos: name: Run Gitleaks test - repo: https://github.com/ansible-community/ansible-lint - rev: v25.6.1 + rev: v25.9.0 hooks: - id: ansible-lint name: Ansible-lint From 0d56df1eda056e7d8619890b4030d6c953055dfb Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 30 Sep 2025 14:53:17 +0100 Subject: [PATCH 069/116] 5.4.1.3 typo fix thanks to @fragglexarmy Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.4.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index ea6eb11..badca42 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -94,7 +94,7 @@ - discovered_warn_days.stdout_lines | length > 0 - item in prelim_interactive_users | map(attribute='username') | list - rhel9cis_force_user_warnage - ansible.builtin.command: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" + ansible.builtin.command: "chage --warndays {{ rhel9cis_pass_warn_age }} {{ item }}" changed_when: true loop: "{{ discovered_warn_days.stdout_lines }}" From 5f64ccd843521c15a3576167369d3108941fa459 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 30 Sep 2025 15:20:23 +0100 Subject: [PATCH 070/116] 5.3.2.1 updated var naming Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.3.2.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index 6e1919c..755e737 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -14,7 +14,7 @@ - rule_5.3.2.1 block: - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Create custom profiles" - when: rhel9cis_authselect_custom_profile_name not in prelim_authselect_current_profile.stdout + when: rhel9cis_authselect_custom_profile_name not in prelim_authselect_profile_list.stdout ansible.builtin.command: "/usr/bin/authselect create-profile {{ rhel9cis_authselect_custom_profile_name }} -b {{ rhel9cis_authselect_default_profile_to_copy }}" changed_when: false args: From 955d3052cc40793b088851020623c7133617c154 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 30 Sep 2025 16:00:26 +0100 Subject: [PATCH 071/116] latest badges and layout Signed-off-by: Mark Bolwell --- README.md | 194 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 117 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 098c50a..781d239 100644 --- a/README.md +++ b/README.md @@ -6,59 +6,93 @@ --- +## Public Repository 📣 + ![Org Stars](https://img.shields.io/github/stars/ansible-lockdown?label=Org%20Stars&style=social) ![Stars](https://img.shields.io/github/stars/ansible-lockdown/RHEL9-CIS?label=Repo%20Stars&style=social) ![Forks](https://img.shields.io/github/forks/ansible-lockdown/RHEL9-CIS?style=social) -![followers](https://img.shields.io/github/followers/ansible-lockdown?style=social) +![Followers](https://img.shields.io/github/followers/ansible-lockdown?style=social) [![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/AnsibleLockdown.svg?style=social&label=Follow%20%40AnsibleLockdown)](https://twitter.com/AnsibleLockdown) - -![Ansible Galaxy Quality](https://img.shields.io/ansible/quality/61781?label=Quality&&logo=ansible) ![Discord Badge](https://img.shields.io/discord/925818806838919229?logo=discord) +![License](https://img.shields.io/github/license/ansible-lockdown/RHEL9-CIS?label=License) + +## Lint & Pre-Commit Tools 🔧 + +[![Pre-Commit.ci](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/RHEL9-CIS/pre-commit-ci.json)](https://results.pre-commit.ci/latest/github/ansible-lockdown/RHEL9-CIS/devel) +![YamlLint](https://img.shields.io/badge/yamllint-Present-brightgreen?style=flat&logo=yaml&logoColor=white) +![Ansible-Lint](https://img.shields.io/badge/ansible--lint-Present-brightgreen?style=flat&logo=ansible&logoColor=white) + +## Community Release Information 📂 + ![Release Branch](https://img.shields.io/badge/Release%20Branch-Main-brightgreen) -![Release Tag](https://img.shields.io/github/v/release/ansible-lockdown/RHEL9-CIS) -![Release Date](https://img.shields.io/github/release-date/ansible-lockdown/RHEL9-CIS) +![Release Tag](https://img.shields.io/github/v/tag/ansible-lockdown/RHEL9-CIS?label=Release%20Tag&&color=success) +![Main Release Date](https://img.shields.io/github/release-date/ansible-lockdown/RHEL9-CIS?label=Release%20Date) +![Benchmark Version Main](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/RHEL9-CIS/benchmark-version-main.json) +![Benchmark Version Devel](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/RHEL9-CIS/benchmark-version-devel.json) [![Main Pipeline Status](https://github.com/ansible-lockdown/RHEL9-CIS/actions/workflows/main_pipeline_validation.yml/badge.svg?)](https://github.com/ansible-lockdown/RHEL9-CIS/actions/workflows/main_pipeline_validation.yml) [![Devel Pipeline Status](https://github.com/ansible-lockdown/RHEL9-CIS/actions/workflows/devel_pipeline_validation.yml/badge.svg?)](https://github.com/ansible-lockdown/RHEL9-CIS/actions/workflows/devel_pipeline_validation.yml) + + ![Devel Commits](https://img.shields.io/github/commit-activity/m/ansible-lockdown/RHEL9-CIS/devel?color=dark%20green&label=Devel%20Branch%20Commits) - -![Issues Open](https://img.shields.io/github/issues-raw/ansible-lockdown/RHEL9-CIS?label=Open%20Issues) -![Issues Closed](https://img.shields.io/github/issues-closed-raw/ansible-lockdown/RHEL9-CIS?label=Closed%20Issues&&color=success) +![Open Issues](https://img.shields.io/github/issues-raw/ansible-lockdown/RHEL9-CIS?label=Open%20Issues) +![Closed Issues](https://img.shields.io/github/issues-closed-raw/ansible-lockdown/RHEL9-CIS?label=Closed%20Issues&&color=success) ![Pull Requests](https://img.shields.io/github/issues-pr/ansible-lockdown/RHEL9-CIS?label=Pull%20Requests) -[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit) - -![License](https://img.shields.io/github/license/ansible-lockdown/RHEL9-CIS?label=License) --- -### Community +## Subscriber Release Information 🔐 -Join us on our [Discord Server](https://www.lockdownenterprise.com/discord) to ask questions, discuss features, or just chat with other Ansible-Lockdown users. +![Private Release Branch](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/release-branch.json) +![Private Benchmark Version](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/benchmark-version.json) + +[![Private Remediate Pipeline](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/remediate.json)](https://github.com/ansible-lockdown/Private-RHEL9-CIS/actions/workflows/main_pipeline_validation.yml) +[![Private GPO Pipeline](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/gpo.json)](https://github.com/ansible-lockdown/Private-RHEL9-CIS/actions/workflows/main_pipeline_validation_gpo.yml) + +![Private Pull Requests](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/prs.json) +![Private Closed Issues](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/issues-closed.json) --- -## Caution(s) +## Looking for support? 🤝 + +[Lockdown Enterprise](https://www.lockdownenterprise.com#GH_AL_WINDOWS_2022_cis) + +[Ansible support](https://www.mindpointgroup.com/cybersecurity-products/ansible-counselor#GH_AL_WINDOWS_2022_cis) + +### Community 💬 + +On our [Discord Server](https://www.lockdownenterprise.com/discord) to ask questions, discuss features, or just chat with other Ansible-Lockdown users + +--- + +## 🚨 Caution(s) 🚨 This role **will make changes to the system** which may have unintended consequences. This is not an auditing tool but rather a remediation tool to be used after an audit has been conducted. - Testing is the most important thing you can do. -- Check Mode is not supported! The role will complete in check mode without errors, but it is not supported and should be used with caution. The RHEL9-CIS-Audit role or a compliance scanner should be used for compliance checking over check mode. +- Check Mode is not guaranteed! 🚫 The role will complete in check mode without errors, but it is not supported and should be used with caution. - This role was developed against a clean install of the Operating System. If you are implementing to an existing system please review this role for any site specific changes that are needed. -- To use release version please point to main branch and relevant release/tag for the cis benchmark you wish to work with. - -- If moving across major releases e.g. v2.0.0 - v3.0.0 there are significant changes to the benchmarks and controls it is suggested to start as a new standard not to upgrade. - -- Containers references vars/is_container.yml this is an example and to be updated for your requirements +- To use release version please point to main branch and relevant release for the cis benchmark you wish to work with. - Did we mention testing?? --- +## Coming From A Previous Release ⏪ + +CIS release always contains changes, it is highly recommended to review the new references and available variables. This have changed significantly since ansible-lockdown initial release. +This is now compatible with python3 if it is found to be the default interpreter. This does come with pre-requisites which it configures the system accordingly. + +Further details can be seen in the [Changelog](./ChangeLog.md) + +--- + ## Matching a security Level for CIS It is possible to to only run level 1 or level 2 controls for CIS. @@ -71,14 +105,34 @@ This is managed using tags: The control found in defaults main also need to reflect this as this control the testing that takes place if you are using the audit component. -## Coming from a previous release +--- +## Requirements ✅ -CIS release always contains changes, it is highly recommended to review the new references and available variables. This have changed significantly since ansible-lockdown initial release. -This is now compatible with python3 if it is found to be the default interpreter. This does come with pre-requisites which it configures the system accordingly. +**General:** -Further details can be seen in the [Changelog](./Changelog.md) +- Basic knowledge of Ansible, below are some links to the Ansible documentation to help get started if you are unfamiliar with Ansible -## Auditing (new) + - [Main Ansible documentation page](https://docs.ansible.com) + - [Ansible Getting Started](https://docs.ansible.com/ansible/latest/user_guide/intro_getting_started.html) + - [Tower User Guide](https://docs.ansible.com/ansible-tower/latest/html/userguide/index.html) + - [Ansible Community Info](https://docs.ansible.com/ansible/latest/community/index.html) +- Functioning Ansible and/or Tower Installed, configured, and running. This includes all of the base Ansible/Tower configurations, needed packages installed, and infrastructure setup. +- Please read through the tasks in this role to gain an understanding of what each control is doing. Some of the tasks are disruptive and can have unintended consequences in a live production system. Also familiarize yourself with the variables in the defaults/main.yml file. + +**Technical Dependencies:** + +RHEL/AlmaLinux/Rocky/Oracle 9 - Other versions are not supported. + +- 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.) +- Python3.8 +- Ansible 2.12+ +- python-def +- libselinux-python + +--- + +## Auditing 🔍 This can be turned on or off within the defaults/main.yml file with the variable run_audit. The value is false by default, please refer to the wiki for more details. The defaults file also populates the goss checks to check only the controls that have been enabled in the ansible role. @@ -109,7 +163,7 @@ PLAY RECAP ********************************************************************* default : ok=270 changed=23 unreachable=0 failed=0 skipped=140 rescued=0 ignored=0 ``` -## Documentation +## Documentation 📖 - [Read The Docs](https://ansible-lockdown.readthedocs.io/en/latest/) - [Getting Started](https://www.lockdownenterprise.com/docs/getting-started-with-lockdown#GH_AL_RH9_cis) @@ -117,38 +171,32 @@ default : ok=270 changed=23 unreachable=0 failed=0 s - [Per-Host Configuration](https://www.lockdownenterprise.com/docs/per-host-lockdown-enterprise-configuration#GH_AL_RH9_cis) - [Getting the Most Out of the Role](https://www.lockdownenterprise.com/docs/get-the-most-out-of-lockdown-enterprise#GH_AL_RH9_cis) -## Requirements - -**General:** - -- Basic knowledge of Ansible, below are some links to the Ansible documentation to help get started if you are unfamiliar with Ansible - - - [Main Ansible documentation page](https://docs.ansible.com) - - [Ansible Getting Started](https://docs.ansible.com/ansible/latest/user_guide/intro_getting_started.html) - - [Tower User Guide](https://docs.ansible.com/ansible-tower/latest/html/userguide/index.html) - - [Ansible Community Info](https://docs.ansible.com/ansible/latest/community/index.html) -- Functioning Ansible and/or Tower Installed, configured, and running. This includes all of the base Ansible/Tower configurations, needed packages installed, and infrastructure setup. -- Please read through the tasks in this role to gain an understanding of what each control is doing. Some of the tasks are disruptive and can have unintended consequences in a live production system. Also familiarize yourself with the variables in the defaults/main.yml file. - -**Technical Dependencies:** - -RHEL/AlmaLinux/Rocky/Oracle 9 - Other versions are not supported. - -- 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.) -- Python3.8 -- Ansible 2.12+ -- python-def -- libselinux-python ## Role Variables This role is designed that the end user should not have to edit the tasks themselves. All customizing should be done via the defaults/main.yml file or with extra vars within the project, job, workflow, etc. -## Tags +## Tags 🏷️ -There are many tags available for added control precision. Each control has it's own set of tags noting what level, if it's scored/notscored, what OS element it relates to, if it's a patch or audit, and the rule number. +There are many tags available for added control precision. Each control has its own set of tags noting what level, what OS element it relates to, whether it's a patch or audit, and the rule number. Additionally, NIST references follow a specific conversion format for consistency and clarity. +### Conversion Format for NIST References: + + 1. Standard Prefix: + + - All references are prefixed with "NIST". + + 2. Standard Types: + + - "800-53" references are formatted as NIST800-53. + - "800-53r5" references are formatted as NIST800-53R5 (with 'R' capitalized). + - "800-171" references are formatted as NIST800-171. + + 3. Details: + + - Section and subsection numbers use periods (.) for numeric separators. + - Parenthetical elements are separated by underscores (_), e.g., IA-5(1)(d) becomes IA-5_1_d. + - Subsection letters (e.g., "b") are appended with an underscore. Below is an example of the tag section from a control within this role. Using this example if you set your run to skip all controls with the tag services, this task will be skipped. The opposite can also happen where you run only controls tagged with services. ```sh @@ -162,33 +210,34 @@ Below is an example of the tag section from a control within this role. Using th - rule_2.2.4 ``` -## Community Contribution + +## Community Contribution 🧑‍🤝‍🧑 We encourage you (the community) to contribute to this role. Please read the rules below. -- Your work is done in your own individual branch. Make sure to Signed-off and GPG sign all commits you intend to merge. +- Your work is done in your own individual branch. Make sure to Signed-off-by and GPG sign all commits you intend to merge. - All community Pull Requests are pulled into the devel branch -- Pull Requests into devel will confirm your commits have a GPG signature, Signed-off, and a functional test before being approved +- Pull Requests into devel will confirm your commits have a GPG signature, Signed-off-by, and a functional test before being approved - Once your changes are merged and a more detailed review is complete, an authorized member will merge your changes into the main branch for a new release +## Pipeline Testing 🔄 + +uses: + +- ansible-core 2.16 +- ansible collections - pulls in the latest version based on requirements file +- runs the audit using the devel branch +- This is an automated test that occurs on pull requests into devel +- self-hosted runners using OpenTofu + ## Known Issues Almalinux BaseOS, EPEL and many cloud providers repositories, do not allow gpgcheck(rule_1.2.1.2) or repo_gpgcheck (rule_1.2.1.3) this will cause issues during the playbook unless or a workaround is found. -## Pipeline Testing -uses: +## Local Testing 💻 -- ansible-core 2.12 -- ansible collections - pulls in the latest version based on requirements file -- runs the audit using the devel branch -- This is an automated test that occurs on pull requests into devel - -## Local Testing - -Molecule can be used to work on this role and test in distinct _scenarios_. - -### examples +### example ```bash molecule test -s default @@ -198,24 +247,15 @@ molecule verify -s localhost local testing uses: -- ansible 2.13.3 +- ansible-core - molecule 4.0.1 - molecule-docker 2.0.0 - molecule-podman 2.0.2 - molecule-vagrant 1.0.0 - molecule-azure 0.5.0 -## Added Extras -- [pre-commit](https://pre-commit.com) can be tested and can be run from within the directory - -```sh -pre-commit run -``` - -## Credits and Thanks - -Based on an original concept by Sam Doran +## Credits and Thanks 🙏 Massive thanks to the fantastic community and all its members. From 383c4651c597ab6f8940f86418ab59a1f2953528 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 1 Oct 2025 17:44:17 +0100 Subject: [PATCH 072/116] added public fix #396 Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index bf03d58..c415e65 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -114,6 +114,7 @@ ansible.builtin.shell: rpm -qi redhat-release | grep Signature # noqa command-instead-of-module changed_when: false failed_when: false + check_mode: false register: prelim_os_gpg_package_valid - name: "PRELIM | PATCH | Force keys to be imported" # noqa command-instead-of-module @@ -207,6 +208,7 @@ ansible.builtin.command: find /sys/class/net/*/ -type d -name wireless register: discover_wireless_adapters changed_when: false + check_mode: false failed_when: discover_wireless_adapters.rc not in [ 0, 1 ] - name: "PRELIM | PATCH | Install Network-Manager | if wireless adapter present" From ee07e5fcce99d6f636e38fc14c5acf21d32ec8f4 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 1 Oct 2025 17:45:50 +0100 Subject: [PATCH 073/116] updated Signed-off-by: Mark Bolwell --- Changelog.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Changelog.md b/Changelog.md index c5870e9..7fe4024 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,13 @@ # Changes to rhel9CIS +# Based on CIS v2.0.0 +Public issues incorporated +Workflow updates +Pre-commit updates +README latest versions +Audit improvements and max-concurrent option added +Benchmark version variable in audit template + ## 2.0.3 - Based on CIS v2.0.0 - Thank you @fragglexarmy From b9478e4cd5a75777f3e1c50ec65bb72926a2a009 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 1 Oct 2025 17:46:37 +0100 Subject: [PATCH 074/116] changed wording for OS supported Signed-off-by: Mark Bolwell --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 781d239..5c75173 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ The control found in defaults main also need to reflect this as this control the **Technical Dependencies:** -RHEL/AlmaLinux/Rocky/Oracle 9 - Other versions are not supported. +RHEL Family OS 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.) From fdc0a7afedc2fa133251e4d1f9a9e873c6462c03 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 2 Oct 2025 09:20:47 +0100 Subject: [PATCH 075/116] fixed typo thanks to @trumbaut #397 Signed-off-by: Mark Bolwell --- tasks/section_3/cis_3.2.x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/section_3/cis_3.2.x.yml b/tasks/section_3/cis_3.2.x.yml index a49d907..415d966 100644 --- a/tasks/section_3/cis_3.2.x.yml +++ b/tasks/section_3/cis_3.2.x.yml @@ -25,8 +25,8 @@ - name: "3.2.1 | PATCH | Ensure dccp kernel module is not available | blacklist" ansible.builtin.lineinfile: path: /etc/modprobe.d/blacklist.conf - regexp: "^(#)?blacklist cramfs(\\s|$)" - line: "blacklist cramfs" + regexp: "^(#)?blacklist dccp(\\s|$)" + line: "blacklist dccp" create: true mode: 'u-x,go-rwx' From 88278381dba320942291db26feee9a16446c0f60 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 2 Oct 2025 09:22:09 +0100 Subject: [PATCH 076/116] updated Signed-off-by: Mark Bolwell --- Changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog.md b/Changelog.md index 7fe4024..34443c4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,8 @@ Pre-commit updates README latest versions Audit improvements and max-concurrent option added Benchmark version variable in audit template +fixed typo thanks to @fragglexarmy #393 +fixed typo thanks to @trumbaut #397 ## 2.0.3 - Based on CIS v2.0.0 From 2cef9e6b298e43c9f8b456d23b2aebdf439baf74 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 2 Oct 2025 12:04:51 +0100 Subject: [PATCH 077/116] updated workflows Signed-off-by: Mark Bolwell --- .../workflows/devel_pipeline_validation.yml | 242 +++++++++--------- .../workflows/main_pipeline_validation.yml | 223 ++++++++-------- 2 files changed, 229 insertions(+), 236 deletions(-) diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index 10750a2..deac4d7 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -4,16 +4,16 @@ on: # yamllint disable-line rule:truthy pull_request_target: - types: [opened, reopened, synchronize] - branches: - - devel - - benchmark* - paths: - - '**.yml' - - '**.sh' - - '**.j2' - - '**.ps1' - - '**.cfg' + types: [opened, reopened, synchronize] + branches: + - devel + - benchmark* + paths: + - '**.yml' + - '**.sh' + - '**.j2' + - '**.ps1' + - '**.cfg' # Allow manual running of workflow workflow_dispatch: @@ -27,133 +27,131 @@ # that can run sequentially or in parallel jobs: # This will create messages for first time contributers and direct them to the Discord server - welcome: - runs-on: ubuntu-latest + welcome: + runs-on: ubuntu-latest - steps: - - uses: actions/first-interaction@main - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - pr-message: |- - Congrats on opening your first pull request and thank you for taking the time to help improve Ansible-Lockdown! - Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well. + steps: + - uses: actions/first-interaction@main + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + issue_message: |- + Congrats on opening your first issue and thank you for taking the time to help improve Ansible-Lockdown! + Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well. + pr_message: |- + Congrats on opening your first pull request and thank you for taking the time to help improve Ansible-Lockdown! + Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well. - # This workflow contains a single job that tests the playbook - playbook-test: - # The type of runner that the job will run on - runs-on: self-hosted - env: - ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} - # Imported as a variable by terraform - TF_VAR_repository: ${{ github.event.repository.name }} - AWS_REGION: "us-east-1" - ANSIBLE_VERSION: ${{ vars.ANSIBLE_RUNNER_VERSION }} - defaults: - run: - shell: bash - working-directory: .github/workflows/github_linux_IaC - # working-directory: .github/workflows + # This workflow contains a single job that tests the playbook + playbook-test: + # The type of runner that the job will run on + runs-on: self-hosted + env: + ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} + # Imported as a variable by terraform + TF_VAR_repository: ${{ github.event.repository.name }} + AWS_REGION: "us-east-1" + ANSIBLE_VERSION: ${{ vars.ANSIBLE_RUNNER_VERSION }} + defaults: + run: + shell: bash + working-directory: .github/workflows/github_linux_IaC + # working-directory: .github/workflows - steps: + steps: - - name: Git clone the lockdown repository to test - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} + - name: Git clone the lockdown repository to test + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - - name: If a variable for IAC_BRANCH is set use that branch - working-directory: .github/workflows - run: | - if [ ${{ vars.IAC_BRANCH }} != '' ]; then - echo "IAC_BRANCH=${{ vars.IAC_BRANCH }}" >> $GITHUB_ENV - echo "Pipeline using the following IAC branch ${{ vars.IAC_BRANCH }}" - else - echo IAC_BRANCH=main >> $GITHUB_ENV - fi + - name: If a variable for IAC_BRANCH is set use that branch + working-directory: .github/workflows + run: | + if [ ${{ vars.IAC_BRANCH }} != '' ]; then + echo "IAC_BRANCH=${{ vars.IAC_BRANCH }}" >> $GITHUB_ENV + echo "Pipeline using the following IAC branch ${{ vars.IAC_BRANCH }}" + else + echo IAC_BRANCH=main >> $GITHUB_ENV + fi - # Pull in terraform code for linux servers - - name: Clone GitHub IaC plan - uses: actions/checkout@v4 - with: - repository: ansible-lockdown/github_linux_IaC - path: .github/workflows/github_linux_IaC - ref: ${{ env.IAC_BRANCH }} + # Pull in terraform code for linux servers + - name: Clone GitHub IaC plan + uses: actions/checkout@v4 + with: + repository: ansible-lockdown/github_linux_IaC + path: .github/workflows/github_linux_IaC + ref: ${{ env.IAC_BRANCH }} - # Uses dedicated restricted role and policy to enable this only for this task - # No credentials are part of github for AWS auth - - name: configure aws credentials - uses: aws-actions/configure-aws-credentials@main - with: - role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }} - role-session-name: ${{ secrets.AWS_ROLE_SESSION }} - aws-region: ${{ env.AWS_REGION }} + # Uses dedicated restricted role and policy to enable this only for this task + # No credentials are part of github for AWS auth + - name: configure aws credentials + uses: aws-actions/configure-aws-credentials@main + with: + role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }} + role-session-name: ${{ secrets.AWS_ROLE_SESSION }} + aws-region: ${{ env.AWS_REGION }} - - name: DEBUG - Show IaC files - if: env.ENABLE_DEBUG == 'true' - run: | - echo "OSVAR = $OSVAR" - echo "benchmark_type = $benchmark_type" - echo "PRIVSUBNET_ID = $AWS_PRIVSUBNET_ID" - echo "VPC_ID" = $AWS_VPC_SECGRP_ID" - pwd - ls - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - benchmark_type: ${{ vars.BENCHMARK_TYPE }} - PRIVSUBNET_ID: ${{ secrets.AWS_PRIVSUBNET_ID }} - VPC_ID: ${{ secrets.AWS_VPC_SECGRP_ID }} + - name: DEBUG - Show IaC files + if: env.ENABLE_DEBUG == 'true' + run: | + echo "OSVAR = $OSVAR" + echo "benchmark_type = $benchmark_type" + pwd + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - name: Tofu init - id: init - run: tofu init - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + - name: Tofu init + id: init + run: tofu init + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - name: Tofu validate - id: validate - run: tofu validate - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + - name: Tofu validate + id: validate + run: tofu validate + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - name: Tofu apply - id: apply - env: - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} - TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} - run: tofu apply -var-file "${OSVAR}.tfvars" --auto-approve -input=false + - name: Tofu apply + id: apply + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu apply -var-file "${OSVAR}.tfvars" --auto-approve -input=false ## Debug Section - - name: DEBUG - Show Ansible hostfile - if: env.ENABLE_DEBUG == 'true' - run: cat hosts.yml + - name: DEBUG - Show Ansible hostfile + if: env.ENABLE_DEBUG == 'true' + run: cat hosts.yml - # Aws deployments taking a while to come up insert sleep or playbook fails + # Aws deployments taking a while to come up insert sleep or playbook fails - - name: Sleep to allow system to come up - run: sleep ${{ vars.BUILD_SLEEPTIME }} + - name: Sleep to allow system to come up + run: sleep ${{ vars.BUILD_SLEEPTIME }} - # Run the Ansible playbook - - name: Run_Ansible_Playbook - env: - ANSIBLE_HOST_KEY_CHECKING: "false" - ANSIBLE_DEPRECATION_WARNINGS: "false" - run: | - /opt/ansible_${{ env.ANSIBLE_VERSION }}_venv/bin/ansible-playbook -i hosts.yml --private-key ~/.ssh/le_runner ../../../site.yml + # Run the Ansible playbook + - name: Run_Ansible_Playbook + env: + ANSIBLE_HOST_KEY_CHECKING: "false" + ANSIBLE_DEPRECATION_WARNINGS: "false" + run: | + /opt/ansible_${{ env.ANSIBLE_VERSION }}_venv/bin/ansible-playbook -i hosts.yml --private-key ~/.ssh/le_runner ../../../site.yml - # Remove test system - User secrets to keep if necessary + # Remove test system - User secrets to keep if necessary - - name: Tofu Destroy - if: always() && env.ENABLE_DEBUG == 'false' - env: - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} - TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} - run: tofu destroy -var-file "${OSVAR}.tfvars" --auto-approve -input=false + - name: Tofu Destroy + if: always() && env.ENABLE_DEBUG == 'false' + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu destroy -var-file "${OSVAR}.tfvars" --auto-approve -input=false diff --git a/.github/workflows/main_pipeline_validation.yml b/.github/workflows/main_pipeline_validation.yml index 6792a00..6c1d2ea 100644 --- a/.github/workflows/main_pipeline_validation.yml +++ b/.github/workflows/main_pipeline_validation.yml @@ -4,16 +4,16 @@ on: # yamllint disable-line rule:truthy pull_request_target: - types: [opened, reopened, synchronize] - branches: - - main - - latest - paths: - - '**.yml' - - '**.sh' - - '**.j2' - - '**.ps1' - - '**.cfg' + types: [opened, reopened, synchronize] + branches: + - main + - latest + paths: + - '**.yml' + - '**.sh' + - '**.j2' + - '**.ps1' + - '**.cfg' # Allow permissions for AWS auth permissions: @@ -24,123 +24,118 @@ # A workflow run is made up of one or more jobs # that can run sequentially or in parallel jobs: + # This workflow contains a single job that tests the playbook + playbook-test: + # The type of runner that the job will run on + runs-on: self-hosted + env: + ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} + # Imported as a variable by terraform + TF_VAR_repository: ${{ github.event.repository.name }} + AWS_REGION : "us-east-1" + ANSIBLE_VERSION: ${{ vars.ANSIBLE_RUNNER_VERSION }} + defaults: + run: + shell: bash + working-directory: .github/workflows/github_linux_IaC + # working-directory: .github/workflows - # This workflow contains a single job that tests the playbook - playbook-test: - # The type of runner that the job will run on - runs-on: self-hosted - env: - ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} - # Imported as a variable by terraform - TF_VAR_repository: ${{ github.event.repository.name }} - AWS_REGION : "us-east-1" - ANSIBLE_VERSION: ${{ vars.ANSIBLE_RUNNER_VERSION }} - defaults: - run: - shell: bash - working-directory: .github/workflows/github_linux_IaC - # working-directory: .github/workflows + steps: - steps: + - name: Git clone the lockdown repository to test + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - - name: Git clone the lockdown repository to test - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} + - name: If a variable for IAC_BRANCH is set use that branch + working-directory: .github/workflows + run: | + if [ ${{ vars.IAC_BRANCH }} != '' ]; then + echo "IAC_BRANCH=${{ vars.IAC_BRANCH }}" >> $GITHUB_ENV + echo "Pipeline using the following IAC branch ${{ vars.IAC_BRANCH }}" + else + echo IAC_BRANCH=main >> $GITHUB_ENV + fi - - name: If a variable for IAC_BRANCH is set use that branch - working-directory: .github/workflows - run: | - if [ ${{ vars.IAC_BRANCH }} != '' ]; then - echo "IAC_BRANCH=${{ vars.IAC_BRANCH }}" >> $GITHUB_ENV - echo "Pipeline using the following IAC branch ${{ vars.IAC_BRANCH }}" - else - echo IAC_BRANCH=main >> $GITHUB_ENV - fi + # Pull in terraform code for linux servers + - name: Clone GitHub IaC plan + uses: actions/checkout@v4 + with: + repository: ansible-lockdown/github_linux_IaC + path: .github/workflows/github_linux_IaC + ref: ${{ env.IAC_BRANCH }} - # Pull in terraform code for linux servers - - name: Clone GitHub IaC plan - uses: actions/checkout@v4 - with: - repository: ansible-lockdown/github_linux_IaC - path: .github/workflows/github_linux_IaC - ref: ${{ env.IAC_BRANCH }} + # Uses dedicated restricted role and policy to enable this only for this task + # No credentials are part of github for AWS auth + - name: configure aws credentials + uses: aws-actions/configure-aws-credentials@main + with: + role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }} + role-session-name: ${{ secrets.AWS_ROLE_SESSION }} + aws-region: ${{ env.AWS_REGION }} - # Uses dedicated restricted role and policy to enable this only for this task - # No credentials are part of github for AWS auth - - name: configure aws credentials - uses: aws-actions/configure-aws-credentials@main - with: - role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }} - role-session-name: ${{ secrets.AWS_ROLE_SESSION }} - aws-region: ${{ env.AWS_REGION }} + - name: DEBUG - Show IaC files + if: env.ENABLE_DEBUG == 'true' + run: | + echo "OSVAR = $OSVAR" + echo "benchmark_type = $benchmark_type" + pwd + ls + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - name: DEBUG - Show IaC files - if: env.ENABLE_DEBUG == 'true' - run: | - echo "OSVAR = $OSVAR" - echo "benchmark_type = $benchmark_type" - echo "PRIVSUBNET_ID = $AWS_PRIVSUBNET_ID" - echo "VPC_ID" = $AWS_VPC_SECGRP_ID" - pwd - ls - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - benchmark_type: ${{ vars.BENCHMARK_TYPE }} - PRIVSUBNET_ID: ${{ secrets.AWS_PRIVSUBNET_ID }} - VPC_ID: ${{ secrets.AWS_VPC_SECGRP_ID }} + - name: Tofu init + id: init + run: tofu init + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - name: Tofu init - id: init - run: tofu init - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + - name: Tofu validate + id: validate + run: tofu validate + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - name: Tofu validate - id: validate - run: tofu validate - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Tofu apply - id: apply - env: - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} - TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} - run: tofu apply -var-file "${OSVAR}.tfvars" --auto-approve -input=false + - name: Tofu apply + id: apply + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu apply -var-file "${OSVAR}.tfvars" --auto-approve -input=false ## Debug Section - - name: DEBUG - Show Ansible hostfile - if: env.ENABLE_DEBUG == 'true' - run: cat hosts.yml + - name: DEBUG - Show Ansible hostfile + if: env.ENABLE_DEBUG == 'true' + run: cat hosts.yml - # Aws deployments taking a while to come up insert sleep or playbook fails + # Aws deployments taking a while to come up insert sleep or playbook fails - - name: Sleep to allow system to come up - run: sleep ${{ vars.BUILD_SLEEPTIME }} + - name: Sleep to allow system to come up + run: sleep ${{ vars.BUILD_SLEEPTIME }} - # Run the Ansible playbook - - name: Run_Ansible_Playbook - env: - ANSIBLE_HOST_KEY_CHECKING: "false" - ANSIBLE_DEPRECATION_WARNINGS: "false" - run: | - /opt/ansible_${{ env.ANSIBLE_VERSION }}_venv/bin/ansible-playbook -i hosts.yml --private-key ~/.ssh/le_runner ../../../site.yml + # Run the Ansible playbook + - name: Run_Ansible_Playbook + env: + ANSIBLE_HOST_KEY_CHECKING: "false" + ANSIBLE_DEPRECATION_WARNINGS: "false" + run: | + /opt/ansible_${{ env.ANSIBLE_VERSION }}_venv/bin/ansible-playbook -i hosts.yml --private-key ~/.ssh/le_runner ../../../site.yml - # Remove test system - User secrets to keep if necessary + # Remove test system - User secrets to keep if necessary - - name: Tofu Destroy - if: always() && env.ENABLE_DEBUG == 'false' - env: - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} - TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} - run: tofu destroy -var-file "${OSVAR}.tfvars" --auto-approve -input=false + - name: Tofu Destroy + if: always() && env.ENABLE_DEBUG == 'false' + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu destroy -var-file "${OSVAR}.tfvars" --auto-approve -input=false From 8f1aba35f67899720153e55d0b2efa102918f75a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 3 Oct 2025 08:13:35 +0100 Subject: [PATCH 078/116] added fix for public #399 Signed-off-by: Mark Bolwell --- Changelog.md | 2 +- tasks/section_5/cis_5.1.x.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Changelog.md b/Changelog.md index 34443c4..5fca72d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,7 +8,7 @@ README latest versions Audit improvements and max-concurrent option added Benchmark version variable in audit template fixed typo thanks to @fragglexarmy #393 -fixed typo thanks to @trumbaut #397 +fixed typo thanks to @trumbaut #397 & #399 ## 2.0.3 - Based on CIS v2.0.0 diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index 42ca036..dc450ea 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -41,8 +41,8 @@ ansible.builtin.file: path: "{{ item.path }}" owner: root - group: root - mode: 'u-x,go-rwx' + group: "{{ 'ssh_keys' if (item.gr_name == 'ssh_keys') else 'root' }}" + mode: "{{ 'u-x,g-wx,o-rwx' if (item.gr_name == 'ssh_keys') else 'u-x,go-rwx' }}" loop: "{{ discovered_ssh_private_host_key.files }}" loop_control: label: "{{ item.path }}" From 16441ddef65ca12ef1603a6ccebc96447dc86d53 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 3 Oct 2025 08:14:13 +0100 Subject: [PATCH 079/116] added badge workflows Signed-off-by: Mark Bolwell --- .../benchmark_tracking_controller.yml | 38 +++++++++++++++++++ .github/workflows/export_badges_private.yml | 27 +++++++++++++ .github/workflows/export_badges_public.yml | 19 ++++++++++ 3 files changed, 84 insertions(+) create mode 100644 .github/workflows/benchmark_tracking_controller.yml create mode 100644 .github/workflows/export_badges_private.yml create mode 100644 .github/workflows/export_badges_public.yml diff --git a/.github/workflows/benchmark_tracking_controller.yml b/.github/workflows/benchmark_tracking_controller.yml new file mode 100644 index 0000000..0d9f515 --- /dev/null +++ b/.github/workflows/benchmark_tracking_controller.yml @@ -0,0 +1,38 @@ +--- + +# GitHub schedules all cron jobs in UTC. +# This expression will run the job every day at 9 AM Eastern Time during Daylight Saving Time (mid-March to early November). +# This expression will run the job every day at 8 AM Eastern Time during Standard Time (early November to mid-March). + +name: Central Benchmark Orchestrator + +on: + push: + branches: + - latest + schedule: + - cron: '0 6 * * *' # Runs daily at 9 AM ET + workflow_dispatch: + +jobs: + call-benchmark-tracker: + if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref_name == 'latest') + name: Start Benchmark Tracker + uses: ansible-lockdown/github_linux_IaC/.github/workflows/benchmark_track.yml@self_hosted + with: + repo_name: ${{ github.repository }} + secrets: + TEAMS_WEBHOOK_URL: ${{ secrets.TEAMS_WEBHOOK_URL }} + BADGE_PUSH_TOKEN: ${{ secrets.BADGE_PUSH_TOKEN }} + DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} + + call-monitor-promotions: + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + name: Monitor Promotions and Auto-Promote + uses: ansible-lockdown/github_linux_IaC/.github/workflows/benchmark_promote.yml@self_hosted + with: + repo_name: ${{ github.repository }} + secrets: + TEAMS_WEBHOOK_URL: ${{ secrets.TEAMS_WEBHOOK_URL }} + BADGE_PUSH_TOKEN: ${{ secrets.BADGE_PUSH_TOKEN }} + DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} diff --git a/.github/workflows/export_badges_private.yml b/.github/workflows/export_badges_private.yml new file mode 100644 index 0000000..d316cbf --- /dev/null +++ b/.github/workflows/export_badges_private.yml @@ -0,0 +1,27 @@ +--- + +name: Export Private Repo Badges + +# Use different minute offsets with the same hourly pattern: +# Repo Group Suggested Cron Expression Explanation +# Group A 0 */6 * * * Starts at top of hour +# Group B 10 */6 * * * Starts at 10 after +# And So On + +on: + push: + branches: + - latest + schedule: + - cron: '0 */6 * * *' + workflow_dispatch: + +jobs: + export-badges: + if: github.event_name == 'workflow_dispatch' || (github.event_name == 'schedule' && startsWith(github.repository, 'ansible-lockdown/Private-')) || (github.event_name == 'push' && github.ref_name == 'latest') + uses: ansible-lockdown/github_linux_IaC/.github/workflows/export_badges_private.yml@self_hosted + with: + # Full org/repo path passed for GitHub API calls (e.g., ansible-lockdown/Private-Windows-2016-CIS) + repo_name: ${{ github.repository }} + secrets: + BADGE_PUSH_TOKEN: ${{ secrets.BADGE_PUSH_TOKEN }} diff --git a/.github/workflows/export_badges_public.yml b/.github/workflows/export_badges_public.yml new file mode 100644 index 0000000..fa4b27f --- /dev/null +++ b/.github/workflows/export_badges_public.yml @@ -0,0 +1,19 @@ +--- + +name: Export Public Repo Badges + +on: + push: + branches: + - main + - devel + workflow_dispatch: + +jobs: + export-badges: + if: github.repository_visibility == 'public' && (github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && (github.ref_name == 'devel' || github.ref_name == 'main'))) + uses: ansible-lockdown/github_linux_IaC/.github/workflows/export_badges_public.yml@self_hosted + with: + repo_name: ${{ github.repository }} + secrets: + BADGE_PUSH_TOKEN: ${{ secrets.BADGE_PUSH_TOKEN }} From 6be41416ecce57928339a6f35e3f247333f85c9d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 16 Oct 2025 14:51:22 +0100 Subject: [PATCH 080/116] updated workflow permissions Signed-off-by: Mark Bolwell --- .github/workflows/devel_pipeline_validation.yml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index deac4d7..8fd728a 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -17,12 +17,6 @@ # Allow manual running of workflow workflow_dispatch: - # Allow permissions for AWS auth - permissions: - id-token: write - contents: read - pull-requests: read - # A workflow run is made up of one or more jobs # that can run sequentially or in parallel jobs: @@ -30,6 +24,10 @@ welcome: runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: - uses: actions/first-interaction@main with: @@ -45,6 +43,13 @@ playbook-test: # The type of runner that the job will run on runs-on: self-hosted + + # Allow permissions for AWS auth + permissions: + id-token: write + contents: read + pull-requests: read + env: ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} # Imported as a variable by terraform From 727ae4515b1c2cd028167d41f3761af7803af23e Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 16 Oct 2025 14:57:24 +0100 Subject: [PATCH 081/116] updated auditd variables Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 0c95ee9..5264dd0 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -87,8 +87,6 @@ audit_max_concurrent: 50 ## Only run Audit do not remediate audit_only: false ### As part of audit_only ### -# This will enable files to be copied back to control node in audit_only mode -fetch_audit_files: false # Path to copy the files to will create dir structure in audit_only mode audit_capture_files_dir: /some/location to copy to on control node ############################# From a525e4a2fbeb5b61f7302b84c69f422dbae9d07b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 16 Oct 2025 14:58:06 +0100 Subject: [PATCH 082/116] Added extra failure for no data Signed-off-by: Mark Bolwell --- tasks/pre_remediation_audit.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index dd9efb4..410473e 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -85,6 +85,7 @@ - name: Pre Audit | Capture audit data if json format ansible.builtin.shell: grep -E '\"summary-line.*Count:.*Failed' "{{ pre_audit_outfile }}" | cut -d'"' -f4 changed_when: false + failed_when: pre_audit_summary.stderr | length > 0 register: pre_audit_summary - name: Pre Audit | Set Fact for audit summary @@ -97,6 +98,7 @@ - name: Pre Audit | Capture audit data if documentation format ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' changed_when: false + failed_when: pre_audit_summary.stderr | length > 0 register: pre_audit_summary - name: Pre Audit | Set Fact for audit summary From 45018f30cb5101063273102492970c56a06a882c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 16 Oct 2025 14:58:52 +0100 Subject: [PATCH 083/116] updated Signed-off-by: Mark Bolwell --- .yamllint | 1 + 1 file changed, 1 insertion(+) diff --git a/.yamllint b/.yamllint index fa7b697..af0d9ab 100644 --- a/.yamllint +++ b/.yamllint @@ -1,4 +1,5 @@ --- + extends: default ignore: | tests/ From 25d3e897fe84f58f935b4572f50de607cb17ff2f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 16 Oct 2025 15:01:57 +0100 Subject: [PATCH 084/116] updated to latest version Signed-off-by: Mark Bolwell --- .../benchmark_tracking_controller.yml | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/.github/workflows/benchmark_tracking_controller.yml b/.github/workflows/benchmark_tracking_controller.yml index 0d9f515..039ec0d 100644 --- a/.github/workflows/benchmark_tracking_controller.yml +++ b/.github/workflows/benchmark_tracking_controller.yml @@ -1,8 +1,22 @@ --- # GitHub schedules all cron jobs in UTC. -# This expression will run the job every day at 9 AM Eastern Time during Daylight Saving Time (mid-March to early November). -# This expression will run the job every day at 8 AM Eastern Time during Standard Time (early November to mid-March). +# ────────────────────────────────────────────────────────────────────────────── +# Schedule: +# - '0 13 * * *' runs at 13:00 UTC every day. +# - This corresponds to: +# • 9:00 AM Eastern **during Daylight Saving Time** (mid-Mar → early-Nov) +# • 8:00 AM Eastern **during Standard Time** (early-Nov → mid-Mar) +# +# Job routing: +# - call-benchmark-tracker: +# • Runs on manual dispatch, and on pushes to the 'latest' branch. +# - call-monitor-promotions: +# • Runs on schedule or manual dispatch **only in repos named ansible-lockdown/Private-***. +# • Skips automatically in public repos (e.g., Windows-2022-CIS) to avoid false failures. +# +# Defense-in-depth: +# - The called promotion workflow may still keep its own guard to ensure only Private-* repos execute it. name: Central Benchmark Orchestrator @@ -11,11 +25,12 @@ on: branches: - latest schedule: - - cron: '0 6 * * *' # Runs daily at 9 AM ET + - cron: '0 13 * * *' # 13:00 UTC → 9 AM ET (DST) / 8 AM ET (Standard Time) workflow_dispatch: jobs: call-benchmark-tracker: + # Run on manual dispatch OR when 'latest' branch receives a push if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref_name == 'latest') name: Start Benchmark Tracker uses: ansible-lockdown/github_linux_IaC/.github/workflows/benchmark_track.yml@self_hosted @@ -27,7 +42,8 @@ jobs: DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} call-monitor-promotions: - if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + # Run on schedule or manual dispatch, but only for Private-* repos + if: (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && startsWith(github.repository, 'ansible-lockdown/Private-') name: Monitor Promotions and Auto-Promote uses: ansible-lockdown/github_linux_IaC/.github/workflows/benchmark_promote.yml@self_hosted with: From ec7226377b73267148b630ee2c36dda3bcbafad7 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 16 Oct 2025 15:18:15 +0100 Subject: [PATCH 085/116] updated template logic for 2.19 Signed-off-by: Mark Bolwell --- templates/audit/99_auditd.rules.j2 | 98 +++++------------------------- 1 file changed, 14 insertions(+), 84 deletions(-) diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 4fa4516..c3c2b6c 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -10,12 +10,7 @@ {% endif %} {% if rhel9cis_rule_6_3_3_2 %} {% set syscalls = ["execve"] %} -{% set arch_syscalls = [] %} -{%- for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor -%} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -C euid!=uid -F auid!=unset -S {{ arch_syscalls|join(',') }} -k user_emulation -a always,exit -F arch=b32 -C euid!=uid -F auid!=unset -S {{ arch_syscalls|join(',') }} -k user_emulation {% endif %} @@ -24,33 +19,18 @@ {% endif %} {% if rhel9cis_rule_6_3_3_4 %} {% set syscalls = ["adjtimex","settimeofday"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -k time-change -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -k time-change {% set syscalls = ["clock_settime"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F a0=0x0 -k time-change -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F a0=0x0 -k time-change -{% endif %} -{% endfor %} -w /etc/localtime -p wa -k time-change {% endif %} {% if rhel9cis_rule_6_3_3_5 %} {% set syscalls = ["sethostname","setdomainname"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -k system-locale -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -k system-locale -w /etc/issue -p wa -k system-locale @@ -68,12 +48,7 @@ {% endif %} {% if rhel9cis_rule_6_3_3_7 %} {% set syscalls = ["creat","open","openat","truncate","ftruncate"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F exit=-EACCES -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F exit=-EPERM -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F exit=-EACCES -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access @@ -91,62 +66,27 @@ {% endif %} {% if rhel9cis_rule_6_3_3_9 %} {% set syscalls = ["chmod","fchmod","fchmodat"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["chown","fchown","lchown","fchownat"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["setxattr","lsetxattr","fsetxattr","removexattr","lremovexattr","fremovexattr"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["chmod","fchmod","fchmodat"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["chown","fchown","lchown","fchownat"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["setxattr","lsetxattr","fsetxattr","removexattr","lremovexattr","fremovexattr"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% endif %} {% if rhel9cis_rule_6_3_3_10 %} {% set syscalls = ["mount"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k mounts -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k mounts {% endif %} @@ -161,12 +101,7 @@ {% endif %} {% if rhel9cis_rule_6_3_3_13 %} {% set syscalls = ["unlink","unlinkat","rename","renameat"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k delete -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k delete {% endif %} @@ -189,12 +124,7 @@ {% if rhel9cis_rule_6_3_3_19 %} -a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k kernel_modules {% set syscalls = ["init_module","finit_module","delete_module","create_module","query_module"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k kernel_modules {% endif %} {% if rhel9cis_rule_6_3_3_20 %} From cd66f4b76fe9865055790eb5496351ae2fb54032 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 16 Oct 2025 15:20:39 +0100 Subject: [PATCH 086/116] updated Signed-off-by: Mark Bolwell --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 5fca72d..9287a24 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ Audit improvements and max-concurrent option added Benchmark version variable in audit template fixed typo thanks to @fragglexarmy #393 fixed typo thanks to @trumbaut #397 & #399 +updated auditd template to be 2.19 complaint ## 2.0.3 - Based on CIS v2.0.0 From 1a3e56c11d39e6626cb9fdf09e5ebd05fd8b5483 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 4 Nov 2025 16:37:40 +0000 Subject: [PATCH 087/116] updated layout Signed-off-by: Mark Bolwell --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 5c75173..dd5bac7 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,6 @@ ## Lint & Pre-Commit Tools 🔧 -[![Pre-Commit.ci](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/RHEL9-CIS/pre-commit-ci.json)](https://results.pre-commit.ci/latest/github/ansible-lockdown/RHEL9-CIS/devel) ![YamlLint](https://img.shields.io/badge/yamllint-Present-brightgreen?style=flat&logo=yaml&logoColor=white) ![Ansible-Lint](https://img.shields.io/badge/ansible--lint-Present-brightgreen?style=flat&logo=ansible&logoColor=white) @@ -49,7 +48,6 @@ ![Private Benchmark Version](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/benchmark-version.json) [![Private Remediate Pipeline](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/remediate.json)](https://github.com/ansible-lockdown/Private-RHEL9-CIS/actions/workflows/main_pipeline_validation.yml) -[![Private GPO Pipeline](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/gpo.json)](https://github.com/ansible-lockdown/Private-RHEL9-CIS/actions/workflows/main_pipeline_validation_gpo.yml) ![Private Pull Requests](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/prs.json) ![Private Closed Issues](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/issues-closed.json) From d2dc32d3babbfdbc99f4a50d05c8041a609cae24 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 4 Nov 2025 16:43:37 +0000 Subject: [PATCH 088/116] updated layout Signed-off-by: Mark Bolwell --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dd5bac7..2d34dd8 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,9 @@ ## Looking for support? 🤝 -[Lockdown Enterprise](https://www.lockdownenterprise.com#GH_AL_WINDOWS_2022_cis) +[Lockdown Enterprise](https://www.lockdownenterprise.com#GH_AL_RH9-CIS) -[Ansible support](https://www.mindpointgroup.com/cybersecurity-products/ansible-counselor#GH_AL_WINDOWS_2022_cis) +[Ansible support](https://www.mindpointgroup.com/cybersecurity-products/ansible-counselor#GH_AL_RH9-CIS) ### Community 💬 From dc570e8b53ab24717917da3a9c18b3641f05fe43 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 25 Nov 2025 09:29:56 +0000 Subject: [PATCH 089/116] add fix provided by @kpi-nourman via discord community Signed-off-by: Mark Bolwell --- templates/etc/dconf/db/gdm.d/01-banner-message.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 index 901e9e0..ec42bfc 100644 --- a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 +++ b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 @@ -4,4 +4,4 @@ [org/gnome/login-screen] banner-message-enable=true -banner-message-text="{{ rhel9cis_warning_banner }}" +banner-message-text="{{ rhel9cis_warning_banner | trim | replace("\n", "\\n") }}" From 32a3473ddc84e3a55b3c4eccab0bb7f19c750263 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 28 Nov 2025 14:35:20 +0000 Subject: [PATCH 090/116] updated Signed-off-by: Mark Bolwell --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a1a002d..a7b9e43 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,13 +42,13 @@ repos: name: Detect Secrets test - repo: https://github.com/gitleaks/gitleaks - rev: v8.27.2 + rev: v8.29.1 hooks: - id: gitleaks name: Run Gitleaks test - repo: https://github.com/ansible-community/ansible-lint - rev: v25.9.0 + rev: v25.11.0 hooks: - id: ansible-lint name: Ansible-lint From ed784d270b70eba79dab647d8cef5b4a42c62a0d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 28 Nov 2025 14:44:59 +0000 Subject: [PATCH 091/116] added fix for issues #413 azure locked passwords Signed-off-by: Mark Bolwell --- tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/main.yml b/tasks/main.yml index 6c5a3f3..f7508f3 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -132,7 +132,7 @@ - rule_5.4.2.4 block: - name: "Ensure root password is set" - ansible.builtin.shell: LC_ALL=C passwd -S root | grep -E "(Password set|Password locked)" + ansible.builtin.shell: LC_ALL=C passwd -S root | grep -E "(\*LOCK\*|Password set|Password locked)" changed_when: false failed_when: prelim_root_passwd_set.rc not in [ 0, 1 ] register: prelim_root_passwd_set From add8ebb81927df1c58d6e9b1f40b377f1120dc73 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 28 Nov 2025 14:47:00 +0000 Subject: [PATCH 092/116] udpated Signed-off-by: Mark Bolwell --- Changelog.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Changelog.md b/Changelog.md index 9287a24..f4088f3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,11 @@ # Changes to rhel9CIS + +# Based on CIS v2.0.0 +pre-commit udpates +public issue #410 thanks to @kpi-nourman +public issue #413 thanks to @bbaassssiiee + # Based on CIS v2.0.0 Public issues incorporated Workflow updates From f80c60bb8a2fd12a7044a01d7840ce765e8f484e Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 1 Dec 2025 10:41:38 +0000 Subject: [PATCH 093/116] updated with correct fix thanks to @bbaassssiiee Signed-off-by: Mark Bolwell --- tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/main.yml b/tasks/main.yml index f7508f3..4e1e5ae 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -132,7 +132,7 @@ - rule_5.4.2.4 block: - name: "Ensure root password is set" - ansible.builtin.shell: LC_ALL=C passwd -S root | grep -E "(\*LOCK\*|Password set|Password locked)" + ansible.builtin.shell: LC_ALL=C passwd -S root | grep -E "(Alternate authentication|Password set|Password locked)" changed_when: false failed_when: prelim_root_passwd_set.rc not in [ 0, 1 ] register: prelim_root_passwd_set From 7ff8e7b6b960e6724ffec0ff8efb6d2995870820 Mon Sep 17 00:00:00 2001 From: George Nalen Date: Tue, 23 Dec 2025 11:20:21 -0500 Subject: [PATCH 094/116] Updated disable IPv6 logic Signed-off-by: George Nalen --- Changelog.md | 3 +++ defaults/main.yml | 4 ++++ tasks/section_3/cis_3.1.x.yml | 19 +++++++++++++++++-- .../etc/sysctl.d/60-disable_ipv6.conf.j2 | 3 +++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index f4088f3..2b02fad 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,8 @@ # Changes to rhel9CIS +# Based on CIS v2.0.0 +Added better sysctl logic to disable IPv6 +Added option to disable IPv6 via sysctl (original method) or via the kernel # Based on CIS v2.0.0 pre-commit udpates diff --git a/defaults/main.yml b/defaults/main.yml index 5264dd0..b5fcd8c 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -731,6 +731,10 @@ rhel9cis_bluetooth_mask: false # This variable governs whether ipv6 is enabled or disabled. rhel9cis_ipv6_required: true +# 3.1.1 Disable IPv6 +# rhel9cis_ipv6_disable defines the method of disabling IPv6, sysctl vs kernel +rhel9cis_ipv6_disable_method: "sysctl" + ## 3.1.2 wireless network requirements # if wireless adapter found allow network manager to be installed rhel9cis_install_network_manager: false diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index a20c0e9..ff9ec46 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -16,15 +16,30 @@ - rule_3.1.1 - NIST800-53R5_CM-7 block: - - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | refresh" + - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | Set vars for sysctl template" + when: "'sysctl' in rhel9cis_ipv6_disable_method" ansible.builtin.set_fact: rhel9cis_sysctl_update: true rhel9cis_flush_ipv6_route: true - - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | disable" + - name: "3.1.1 | AUDIT | Ensure IPv6 status is identified | Message out implementation info" + when: "'sysctl' in rhel9cis_ipv6_disable_method" ansible.builtin.debug: msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-disable_ipv6.conf" + - name: "3.1.1 | AUDIT | Ensure IPv6 status is identified | Find IPv6 status" + when: "'kernel' in rhel9cis_ipv6_disable_method" + ansible.builtin.command: grubby --info=ALL + changed_when: false + failed_when: false + register: discovered_rhel9cis_3_1_1_ipv6_status + + - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | Disable IPV6 via Kernel" + when: + - "'kernel' in rhel9cis_ipv6_disable_method" + - "'ipv6.disable=1' not in discovered_rhel9cis_3_1_1_ipv6_status.stdout" + ansible.builtin.shell: grubby --update-kernel=ALL --args="ipv6.disable=1" + - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled" when: - rhel9cis_rule_3_1_2 diff --git a/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 b/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 index bdded40..b4b5318 100644 --- a/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 +++ b/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 @@ -4,4 +4,7 @@ {% if rhel9cis_rule_3_1_1 and not rhel9cis_ipv6_required %} net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 +{% for interface in ansible_interfaces %} +net.ipv6.conf.{{ interface }}.disable_ipv6 = 1 +{% endfor %} {% endif %} From ac83c8cf3573c23764ffda1cc04a1edb87c4cb36 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Mon, 29 Dec 2025 17:18:05 -0500 Subject: [PATCH 095/116] Update audit vars to add rhel9cis_ipv6_disable_method: {{ rhel9cis_ipv6_disable_method }} Signed-off-by: Frederick Witty --- templates/ansible_vars_goss.yml.j2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index e709a10..abc374c 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -206,6 +206,8 @@ rhel9cis_rule_2_4_2_1: {{ rhel9cis_rule_2_4_2_1 }} rhel9cis_rule_3_1_1: {{ rhel9cis_rule_3_1_1 }} rhel9cis_rule_3_1_2: {{ rhel9cis_rule_3_1_2 }} rhel9cis_rule_3_1_3: {{ rhel9cis_rule_3_1_3 }} +rhel9cis_ipv6_disable_method: {{ rhel9cis_ipv6_disable_method }} + ## Network Kernel Modules rhel9cis_rule_3_2_1: {{ rhel9cis_rule_3_2_1 }} rhel9cis_rule_3_2_2: {{ rhel9cis_rule_3_2_2 }} From 309ff4cdd7f86d78989627b19d3703de4fb401ec Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Thu, 8 Jan 2026 14:08:35 -0500 Subject: [PATCH 096/116] Fixes from Public Issue 418 and 419 + Lic year Signed-off-by: Frederick Witty --- Changelog.md | 11 +++++------ LICENSE | 2 +- tasks/section_5/cis_5.1.x.yml | 2 ++ tasks/section_6/cis_6.2.2.x.yml | 6 +++--- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Changelog.md b/Changelog.md index 2b02fad..c5ef6e1 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,15 +1,14 @@ -# Changes to rhel9CIS +# Changes to RHEL9CIS -# Based on CIS v2.0.0 +## 2.0.4 - Based on CIS v2.0.0 + +addressed issue #419, thank you @aaronk1 +addressed issue #418 thank you @bbaassssiiee Added better sysctl logic to disable IPv6 Added option to disable IPv6 via sysctl (original method) or via the kernel - -# Based on CIS v2.0.0 pre-commit udpates public issue #410 thanks to @kpi-nourman public issue #413 thanks to @bbaassssiiee - -# Based on CIS v2.0.0 Public issues incorporated Workflow updates Pre-commit updates diff --git a/LICENSE b/LICENSE index 7e51eb7..bed11b4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 Mindpoint Group - A Tyto Athene Company / Ansible Lockdown +Copyright (c) 2026 Mindpoint Group - A Tyto Athene Company / Ansible Lockdown Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index dc450ea..2b372de 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -411,6 +411,8 @@ path: "{{ rhel9cis_sshd_config_file }}" regexp: '^(#)?MaxAuthTries \d' line: 'MaxAuthTries {{ rhel9cis_ssh_maxauthtries }}' + insertbefore: "^Match" + firstmatch: true validate: sshd -t -f %s notify: Restart sshd diff --git a/tasks/section_6/cis_6.2.2.x.yml b/tasks/section_6/cis_6.2.2.x.yml index fe0f8c4..82302ed 100644 --- a/tasks/section_6/cis_6.2.2.x.yml +++ b/tasks/section_6/cis_6.2.2.x.yml @@ -25,7 +25,7 @@ - name: "6.2.2.2 | PATCH | Ensure journald ForwardToSyslog is disabled | comment out current entries" ansible.builtin.replace: path: /etc/systemd/journald.conf - regexp: ^(\s*ForwardToSyslog) + regexp: ^(\s*ForwardToSyslog\s*=.*) replace: '#\1' - name: "6.2.2.3 | PATCH | Ensure journald Compress is configured" @@ -50,7 +50,7 @@ - name: "6.2.2.3 | PATCH | Ensure journald Compress is configured | comment out current entries" ansible.builtin.replace: path: /etc/systemd/journald.conf - regexp: (?i)(\s*compress=) + regexp: ^(\s*Compress\s*=.*) replace: '#\1' - name: "6.2.2.4 | PATCH | Ensure journald Storage is configured" @@ -76,5 +76,5 @@ - name: "6.2.2.4 | PATCH | Ensure journald Storage is configured | comment out current entries" ansible.builtin.replace: path: /etc/systemd/journald.conf - regexp: (?i)(\s*storage=) + regexp: ^(\s*Storage\s*=.*) replace: '#\1' From 10f88cc1a352be365215a7aff6751927382e58f1 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Thu, 8 Jan 2026 14:13:07 -0500 Subject: [PATCH 097/116] update vars to rhel9 Signed-off-by: Frederick Witty --- molecule/wsl/converge.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/molecule/wsl/converge.yml b/molecule/wsl/converge.yml index 5128600..1725e67 100644 --- a/molecule/wsl/converge.yml +++ b/molecule/wsl/converge.yml @@ -8,16 +8,16 @@ vars: ansible_user: "{{ lookup('env', 'USER') }}" system_is_container: true - rhel8cis_selinux_disable: true + rhel9cis_selinux_disable: true role_name: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}" - rhel8cis_rule_5_3_4: false - rhel8cis_rule_1_1_10: false - rhel8cis_rsyslog_ansiblemanaged: false - rhel8cis_rule_3_4_1_3: false - rhel8cis_rule_3_4_1_4: false - rhel8cis_rule_4_2_1_2: false - rhel8cis_rule_4_2_1_4: false - rhel8cis_rule_5_1_1: false + rhel9cis_rule_5_3_4: false + rhel9cis_rule_1_1_10: false + rhel9cis_rsyslog_ansiblemanaged: false + rhel9cis_rule_3_4_1_3: false + rhel9cis_rule_3_4_1_4: false + rhel9cis_rule_4_2_1_2: false + rhel9cis_rule_4_2_1_4: false + rhel9cis_rule_5_1_1: false pre_tasks: tasks: From 173fbd3254d2e74218f8e7edf6b2a91d7d53b008 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Thu, 8 Jan 2026 14:26:24 -0500 Subject: [PATCH 098/116] Linting Signed-off-by: Frederick Witty --- defaults/main.yml | 2 +- tasks/LE_audit_setup.yml | 1 + tasks/section_1/cis_1.1.2.3.x.yml | 1 + vars/OracleLinux.yml | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index b5fcd8c..2fdb1f6 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -245,7 +245,7 @@ rhel9cis_rule_1_8_8: true rhel9cis_rule_1_8_9: true rhel9cis_rule_1_8_10: true -# Section 2 rules are controling Services (Special Purpose Services, and service clients) +# Section 2 rules are controlling Services (Special Purpose Services, and service clients) ## Configure Server Services rhel9cis_rule_2_1_1: true rhel9cis_rule_2_1_2: true diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index d784dc1..53293e7 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -1,4 +1,5 @@ --- + - name: Pre Audit Setup | Set audit package name block: - name: Pre Audit Setup | Set audit package name | 64bit diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml index 635648d..efb1dc3 100644 --- a/tasks/section_1/cis_1.1.2.3.x.yml +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -1,4 +1,5 @@ --- + - name: "1.1.2.3.1 | PATCH | Ensure /home is a separate partition" when: - rhel9cis_rule_1_1_2_3_1 diff --git a/vars/OracleLinux.yml b/vars/OracleLinux.yml index 64927cc..f407fa5 100644 --- a/vars/OracleLinux.yml +++ b/vars/OracleLinux.yml @@ -1,4 +1,5 @@ --- + # OS Specific Settings os_gpg_key_pubkey_name: gpg-pubkey-8d8b756f-629e59ec os_gpg_key_pubkey_content: "Oracle Linux (release key 1) " From e65df16f6782db76e3a6ade7df0edbf2f638f4c8 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Thu, 8 Jan 2026 14:33:16 -0500 Subject: [PATCH 099/116] Update 3.1.1 Signed-off-by: Frederick Witty --- tasks/section_3/cis_3.1.x.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index ff9ec46..7099e55 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -38,7 +38,8 @@ when: - "'kernel' in rhel9cis_ipv6_disable_method" - "'ipv6.disable=1' not in discovered_rhel9cis_3_1_1_ipv6_status.stdout" - ansible.builtin.shell: grubby --update-kernel=ALL --args="ipv6.disable=1" + ansible.builtin.command: grubby --update-kernel=ALL --args="ipv6.disable=1" + changed_when: discovered_rhel9cis_3_1_1_ipv6_status.rc == 0 - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled" when: From 63d2ce7d2da367d3b826920079d6528f287ba6e6 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Sun, 1 Feb 2026 19:53:50 +0000 Subject: [PATCH 100/116] removed legacy option Signed-off-by: Mark Bolwell --- .ansible-lint | 1 - 1 file changed, 1 deletion(-) diff --git a/.ansible-lint b/.ansible-lint index 3b7c373..7aa8478 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -1,6 +1,5 @@ --- -parseable: true quiet: true skip_list: - 'package-latest' From db0b08762e19d48137073a53adf18d0f23f32809 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Sun, 1 Feb 2026 19:54:22 +0000 Subject: [PATCH 101/116] fixed typo thats to Eugene @Frequentis Signed-off-by: Mark Bolwell --- tasks/section_7/cis_7.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_7/cis_7.1.x.yml b/tasks/section_7/cis_7.1.x.yml index b23fb89..d958c9b 100644 --- a/tasks/section_7/cis_7.1.x.yml +++ b/tasks/section_7/cis_7.1.x.yml @@ -58,7 +58,7 @@ - level1-server - level1-workstation - patch - - permissionss + - permissions - rule_7.1.4 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 From 3e27eb88de5fc13af7ebf9b4547ae1a7a5c2553d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Sun, 1 Feb 2026 20:09:10 +0000 Subject: [PATCH 102/116] Updated Signed-off-by: Mark Bolwell --- CONTRIBUTING.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 13e0b49..d7cdcbf 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -7,7 +7,7 @@ Rules 2) All commits must have Signed-off-by (Signed-off-by: Joan Doe ) in the commit message (details in Signing section) 3) All work is done in your own branch 4) All pull requests go into the devel branch. There are automated checks for signed commits, signoff in commit message, and functional testing) -5) Be open and nice to eachother +5) Be open and nice to each other Workflow -------- From 2708a2840917ef8c8b2804d05604a8628eb13aba Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Sun, 1 Feb 2026 20:09:48 +0000 Subject: [PATCH 103/116] removed schedule tasks Signed-off-by: Mark Bolwell --- .github/workflows/export_badges_private.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/export_badges_private.yml b/.github/workflows/export_badges_private.yml index d316cbf..761c42e 100644 --- a/.github/workflows/export_badges_private.yml +++ b/.github/workflows/export_badges_private.yml @@ -12,8 +12,6 @@ on: push: branches: - latest - schedule: - - cron: '0 */6 * * *' workflow_dispatch: jobs: From eb9c96f335d809b39f427eb8deb066ee34d1c67a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Sun, 1 Feb 2026 20:13:34 +0000 Subject: [PATCH 104/116] Updated Company title Signed-off-by: Mark Bolwell --- templates/audit/98_auditd_exception.rules.j2 | 2 +- templates/audit/99_auditd.rules.j2 | 2 +- templates/etc/ansible/compliance_facts.j2 | 2 +- templates/etc/cron.d/aide.cron.j2 | 2 +- templates/etc/dconf/db/00-automount_lock.j2 | 2 +- templates/etc/dconf/db/00-autorun_lock.j2 | 2 +- templates/etc/dconf/db/00-media-automount.j2 | 2 +- templates/etc/dconf/db/00-media-autorun.j2 | 2 +- templates/etc/dconf/db/00-screensaver.j2 | 2 +- templates/etc/dconf/db/00-screensaver_lock.j2 | 2 +- templates/etc/dconf/db/gdm.d/01-banner-message.j2 | 2 +- vars/main.yml | 2 ++ 12 files changed, 13 insertions(+), 11 deletions(-) diff --git a/templates/audit/98_auditd_exception.rules.j2 b/templates/audit/98_auditd_exception.rules.j2 index 70ebd03..1bec877 100644 --- a/templates/audit/98_auditd_exception.rules.j2 +++ b/templates/audit/98_auditd_exception.rules.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by {{ company_title }} ### YOUR CHANGES WILL BE LOST! # This file contains users whose actions are not logged by auditd diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index c3c2b6c..0a0cadf 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by {{ company_title }} ### YOUR CHANGES WILL BE LOST! # This template will set all of the auditd configurations via a handler in the role in one task instead of individually diff --git a/templates/etc/ansible/compliance_facts.j2 b/templates/etc/ansible/compliance_facts.j2 index f8725e1..896c159 100644 --- a/templates/etc/ansible/compliance_facts.j2 +++ b/templates/etc/ansible/compliance_facts.j2 @@ -1,6 +1,6 @@ # CIS Hardening Carried out # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by {{ company_title }} [lockdown_details] # Benchmark release diff --git a/templates/etc/cron.d/aide.cron.j2 b/templates/etc/cron.d/aide.cron.j2 index 4c1af92..15ea95f 100644 --- a/templates/etc/cron.d/aide.cron.j2 +++ b/templates/etc/cron.d/aide.cron.j2 @@ -1,7 +1,7 @@ # Run AIDE integrity check ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by {{ company_title }} ### YOUR CHANGES WILL BE LOST! # CIS 1.3.2 diff --git a/templates/etc/dconf/db/00-automount_lock.j2 b/templates/etc/dconf/db/00-automount_lock.j2 index 0e55b5a..f6ac336 100644 --- a/templates/etc/dconf/db/00-automount_lock.j2 +++ b/templates/etc/dconf/db/00-automount_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by {{ company_title }} # Lock desktop media-handling automount setting /org/gnome/desktop/media-handling/automount diff --git a/templates/etc/dconf/db/00-autorun_lock.j2 b/templates/etc/dconf/db/00-autorun_lock.j2 index cf9ed5d..17dcd56 100644 --- a/templates/etc/dconf/db/00-autorun_lock.j2 +++ b/templates/etc/dconf/db/00-autorun_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by {{ company_title }} # Lock desktop media-handling settings /org/gnome/desktop/media-handling/autorun-never diff --git a/templates/etc/dconf/db/00-media-automount.j2 b/templates/etc/dconf/db/00-media-automount.j2 index 640538c..84f086d 100644 --- a/templates/etc/dconf/db/00-media-automount.j2 +++ b/templates/etc/dconf/db/00-media-automount.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by {{ company_title }} [org/gnome/desktop/media-handling] automount=false diff --git a/templates/etc/dconf/db/00-media-autorun.j2 b/templates/etc/dconf/db/00-media-autorun.j2 index 382469c..528f1be 100644 --- a/templates/etc/dconf/db/00-media-autorun.j2 +++ b/templates/etc/dconf/db/00-media-autorun.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by {{ company_title }} [org/gnome/desktop/media-handling] autorun-never=true diff --git a/templates/etc/dconf/db/00-screensaver.j2 b/templates/etc/dconf/db/00-screensaver.j2 index a747336..a6c6894 100644 --- a/templates/etc/dconf/db/00-screensaver.j2 +++ b/templates/etc/dconf/db/00-screensaver.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by {{ company_title }} # Specify the dconf path [org/gnome/desktop/session] diff --git a/templates/etc/dconf/db/00-screensaver_lock.j2 b/templates/etc/dconf/db/00-screensaver_lock.j2 index 5988316..ab8d41d 100644 --- a/templates/etc/dconf/db/00-screensaver_lock.j2 +++ b/templates/etc/dconf/db/00-screensaver_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by {{ company_title }} # Lock desktop screensaver idle-delay setting /org/gnome/desktop/session/idle-delay diff --git a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 index ec42bfc..b5fac22 100644 --- a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 +++ b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by Mindpoint Group - A Tyto Athene Company +# provided by {{ company_title }} [org/gnome/login-screen] banner-message-enable=true diff --git a/vars/main.yml b/vars/main.yml index 9337d58..a6ee2b5 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -74,3 +74,5 @@ audit_bins: - /sbin/autrace - /sbin/auditd - /sbin/augenrules + +company_title: 'Mindpoint Group - A Tyto Athene Company' From c7567a98aca9cd331c51b051290610db01e353c3 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 3 Feb 2026 08:57:45 +0000 Subject: [PATCH 105/116] fixed tags and audit logic Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index c415e65..400c88d 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -4,7 +4,9 @@ # List users in order to look up files inside each home directory - name: "PRELIM | Include audit specific variables" - when: run_audit or audit_only or setup_audit + when: + - run_audit or audit_only + - setup_audit tags: - setup_audit - run_audit @@ -12,7 +14,8 @@ file: audit.yml - name: "PRELIM | Include pre-remediation audit tasks" - when: run_audit or audit_only or setup_audit + when: + - run_audit or audit_only tags: run_audit ansible.builtin.import_tasks: pre_remediation_audit.yml @@ -92,6 +95,11 @@ - rhel9cis_rule_1_2_1_1 - ansible_facts.distribution != 'RedHat' - ansible_facts.distribution != 'OracleLinux' + tags: + - level1-server + - level1-workstation + - rule_1.2.1.1 + - gpg ansible.builtin.package: name: "{{ gpg_key_package }}" state: latest From 943b5704840155aba4eac9663b9e2f8bfe5e8b6a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 3 Feb 2026 09:01:55 +0000 Subject: [PATCH 106/116] incorporated PR 345 thanks to @thulium-drake Signed-off-by: Mark Bolwell --- defaults/main.yml | 14 +++---- filter_plugins/grub_hash.py | 73 +++++++++++++++++++++++++++++++++++ tasks/main.yml | 10 ++--- tasks/section_1/cis_1.4.x.yml | 2 +- 4 files changed, 85 insertions(+), 14 deletions(-) create mode 100644 filter_plugins/grub_hash.py diff --git a/defaults/main.yml b/defaults/main.yml index 2fdb1f6..b026a33 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -565,15 +565,15 @@ rhel9cis_selinux_pol: targeted # Even though logging still occurs. rhel9cis_selinux_enforce: enforcing -## Control 1.4.1 -# This variable will store the hashed GRUB bootloader password to be stored in '/boot/grub2/user.cfg' file. The default value -# must be changed to a value that may be generated with this command 'grub2-mkpasswd-pbkdf2' and must comply with -# this format: 'grub.pbkdf2.sha512...' -rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret - ## Control 1.4.1 # This variable governs whether a bootloader password should be set in '/boot/grub2/user.cfg' file. -rhel9cis_set_boot_pass: true +rhel9cis_set_boot_pass: false + +# This variable will store the GRUB bootloader password to be stored in '/boot/grub2/user.cfg' file. The default value must be changed. +rhel9cis_bootloader_password: 'password' # pragma: allowlist secret + +# Set this value to anything secure to have predictable hashes, which will prevent unnecessary changes +rhel9cis_bootloader_salt: '' ## Controls 1.6.x and Controls 5.1.x # This variable governs if current Ansible role should manage system-wide crypto policy. diff --git a/filter_plugins/grub_hash.py b/filter_plugins/grub_hash.py new file mode 100644 index 0000000..245756b --- /dev/null +++ b/filter_plugins/grub_hash.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (c) 2025, Jeffrey van Pelt +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +from __future__ import annotations + +DOCUMENTATION = r""" +name: grub_hash +short_description: Generate a GRUB2 password hash +version_added: 1.0.0 +author: Jeffrey van Pelt (@Thulium-Drake) +description: + - Generate a GRUB2 password hash from the input +options: + _input: + description: The desired password for the GRUB bootloader + type: string + required: true + salt: + description: The salt used to generate the hash + type: string + required: false + rounds: + description: The amount of rounds to run the PBKDF2 function + type: int + required: false +""" + +EXAMPLES = r""" +- name: 'Generate hash with defaults' + ansible.builtin.debug: + msg: "{{ 'mango123!' | grub_hash }}" + +- name: 'Generate hash with custom rounds and salt' + ansible.builtin.debug: + msg: "{{ 'mango123!' | grub_hash(rounds=10001, salt='andpepper') }}" + # Produces: grub.pbkdf2.sha512.10001.616E64706570706572.4C6AEA2A811B4059D4F47AEA36B77DB185B41E9F08ECC3C4C694427DB876C21B24E6CBA0319053E4F1431CDEE83076398C73B9AA8F50A7355E446229BC69A97C +""" + +RETURN = r""" +_value: + description: A GRUB2 password hash + type: string +""" + +from ansible.errors import AnsibleFilterError +import os +import base64 +from passlib.hash import grub_pbkdf2_sha512 + +def grub_hash(password, rounds=10000, salt=None): + if salt is None: + # Generate 64-byte salt if not provided + salt = os.urandom(64) + + # Check if the salt, when not generated, is a valid bytes value and attempt to convert if needed + if not isinstance(salt, bytes): + try: + salt = salt.encode("utf-8") + except AttributeError: + raise TypeError("Salt must be a string, not int.") + + # Configure hash generator + pbkdf2_generator = grub_pbkdf2_sha512.using(rounds=rounds, salt=salt) + return pbkdf2_generator.hash(password) + +class FilterModule(object): + def filters(self): + return { + 'grub_hash': grub_hash + } diff --git a/tasks/main.yml b/tasks/main.yml index 4e1e5ae..c0d3ba3 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -41,14 +41,14 @@ fail_msg: "Crypto policy is not a permitted version" success_msg: "Crypto policy is a permitted version" -- name: "Check rhel9cis_bootloader_password_hash variable has been changed" +- name: "Check rhel9cis_bootloader_password variable has been changed" when: - rhel9cis_set_boot_pass - rhel9cis_rule_1_4_1 tags: always ansible.builtin.assert: - that: rhel9cis_bootloader_password_hash.find('grub.pbkdf2.sha512') != -1 and rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret - msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password_hash variable has not been set correctly" + that: rhel9cis_bootloader_password != 'password' # pragma: allowlist secret + msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password variable has not been set correctly" - name: "Check crypto-policy module input" when: @@ -154,9 +154,7 @@ file: "{{ ansible_facts.distribution }}.yml" - name: "Include preliminary steps" - tags: - - prelim_tasks - - always + tags: prelim_tasks ansible.builtin.import_tasks: file: prelim.yml diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index 5969dff..1615066 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -13,7 +13,7 @@ - NIST800-53R5_AC-3 ansible.builtin.copy: dest: /boot/grub2/user.cfg - content: "GRUB2_PASSWORD={{ rhel9cis_bootloader_password_hash }}" # noqa template-instead-of-copy + content: "GRUB2_PASSWORD={{ rhel9cis_bootloader_password_hash | default(rhel9cis_bootloader_password | grub_hash(salt=rhel9cis_bootloader_salt)) }}" # noqa template-instead-of-copy owner: root group: root mode: 'go-rwx' From 83ee942ecf5955ddc68a607329ead9f420172a8f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 3 Feb 2026 09:18:36 +0000 Subject: [PATCH 107/116] updated Signed-off-by: Mark Bolwell --- Changelog.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index c5ef6e1..8c4bfbe 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,7 +6,7 @@ addressed issue #419, thank you @aaronk1 addressed issue #418 thank you @bbaassssiiee Added better sysctl logic to disable IPv6 Added option to disable IPv6 via sysctl (original method) or via the kernel -pre-commit udpates +pre-commit updates public issue #410 thanks to @kpi-nourman public issue #413 thanks to @bbaassssiiee Public issues incorporated @@ -18,6 +18,8 @@ Benchmark version variable in audit template fixed typo thanks to @fragglexarmy #393 fixed typo thanks to @trumbaut #397 & #399 updated auditd template to be 2.19 complaint +PR345 thanks to thulium-drake boot password hash +tidy up tags on tasks/main.yml ## 2.0.3 - Based on CIS v2.0.0 From f1786fe20f89e6dc9c8730e92f771a6789ac9d52 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 5 Feb 2026 10:39:04 +0000 Subject: [PATCH 108/116] added passlib dependency documentation Signed-off-by: Mark Bolwell --- Changelog.md | 2 +- README.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 8c4bfbe..bd7162b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -18,7 +18,7 @@ Benchmark version variable in audit template fixed typo thanks to @fragglexarmy #393 fixed typo thanks to @trumbaut #397 & #399 updated auditd template to be 2.19 complaint -PR345 thanks to thulium-drake boot password hash +PR345 thanks to thulium-drake boot password hash - if used needs passlib module tidy up tags on tasks/main.yml ## 2.0.3 - Based on CIS v2.0.0 diff --git a/README.md b/README.md index 2d34dd8..62e316f 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,9 @@ RHEL Family OS 9 - python-def - libselinux-python +If you are using the option to create your own bootloader hash the ansible controller +- passlib + --- ## Auditing 🔍 From 9b091984db24e60a32a6f068efe0cbd41e030ca5 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 5 Feb 2026 17:53:55 +0000 Subject: [PATCH 109/116] updated logic to allow manual hash to be added or filter Signed-off-by: Mark Bolwell --- defaults/main.yml | 4 ++++ tasks/main.yml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index b026a33..931ea93 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -569,6 +569,10 @@ rhel9cis_selinux_enforce: enforcing # This variable governs whether a bootloader password should be set in '/boot/grub2/user.cfg' file. rhel9cis_set_boot_pass: false +# Either set rhel9cis_bootloader_password_hash or rhel9cis_bootloader_password and rhel9cis_bootloader_salt +# If you are not using the bootloader hash filter you can set it here if the encrypted format e.g. grub.pbkdf2.sha512.hashstring +rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret + # This variable will store the GRUB bootloader password to be stored in '/boot/grub2/user.cfg' file. The default value must be changed. rhel9cis_bootloader_password: 'password' # pragma: allowlist secret diff --git a/tasks/main.yml b/tasks/main.yml index c0d3ba3..4525a74 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -47,7 +47,7 @@ - rhel9cis_rule_1_4_1 tags: always ansible.builtin.assert: - that: rhel9cis_bootloader_password != 'password' # pragma: allowlist secret + that: rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword' or (rhel9cis_bootloader_salt != '' and rhel9cis_bootloader_password != 'password') # pragma: allowlist secret msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password variable has not been set correctly" - name: "Check crypto-policy module input" From 9a3f458db0283f729c754fcd185f6681c74b120d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 5 Feb 2026 18:10:29 +0000 Subject: [PATCH 110/116] Updated bootloader password logic and enabled old methods without change Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 ++ tasks/section_1/cis_1.4.x.yml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 931ea93..24ec0b6 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -579,6 +579,8 @@ rhel9cis_bootloader_password: 'password' # pragma: allowlist secret # Set this value to anything secure to have predictable hashes, which will prevent unnecessary changes rhel9cis_bootloader_salt: '' +rhel9_compiled_bootloader_password: "{% if rhel9cis_bootloader_salt != '' %}(rhel9cis_bootloader_password | grub_hash(salt=rhel9cis_bootloader_salt)) }}{% else %}{{ rhel9cis_bootloader_password_hash }}{% endif %}" # noqa template-instead-of-copy + ## Controls 1.6.x and Controls 5.1.x # This variable governs if current Ansible role should manage system-wide crypto policy. rhel9cis_crypto_policy_ansiblemanaged: true diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index 1615066..4476d30 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -13,7 +13,7 @@ - NIST800-53R5_AC-3 ansible.builtin.copy: dest: /boot/grub2/user.cfg - content: "GRUB2_PASSWORD={{ rhel9cis_bootloader_password_hash | default(rhel9cis_bootloader_password | grub_hash(salt=rhel9cis_bootloader_salt)) }}" # noqa template-instead-of-copy + content: "GRUB2_PASSWORD={{ rhel9_compiled_bootloader_password }}" # noqa template-instead-of-copy owner: root group: root mode: 'go-rwx' From 34428013999c4c56d4abb5aad6a1481804592f53 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 5 Feb 2026 20:28:52 +0000 Subject: [PATCH 111/116] tidy up of variables and warning for bootloader password Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 -- tasks/main.yml | 2 +- vars/main.yml | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 24ec0b6..931ea93 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -579,8 +579,6 @@ rhel9cis_bootloader_password: 'password' # pragma: allowlist secret # Set this value to anything secure to have predictable hashes, which will prevent unnecessary changes rhel9cis_bootloader_salt: '' -rhel9_compiled_bootloader_password: "{% if rhel9cis_bootloader_salt != '' %}(rhel9cis_bootloader_password | grub_hash(salt=rhel9cis_bootloader_salt)) }}{% else %}{{ rhel9cis_bootloader_password_hash }}{% endif %}" # noqa template-instead-of-copy - ## Controls 1.6.x and Controls 5.1.x # This variable governs if current Ansible role should manage system-wide crypto policy. rhel9cis_crypto_policy_ansiblemanaged: true diff --git a/tasks/main.yml b/tasks/main.yml index 4525a74..d6325fd 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -48,7 +48,7 @@ tags: always ansible.builtin.assert: that: rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword' or (rhel9cis_bootloader_salt != '' and rhel9cis_bootloader_password != 'password') # pragma: allowlist secret - msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password variable has not been set correctly" + msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password or rhel9cis_bootloader_password_hash variable has not been set correctly" - name: "Check crypto-policy module input" when: diff --git a/vars/main.yml b/vars/main.yml index a6ee2b5..dfff3c5 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -24,6 +24,8 @@ rhel9cis_allowed_crypto_policies_modules: - 'NO-SSHWEAKMAC' - 'NO-WEAKMAC' +rhel9_compiled_bootloader_password: "{% if rhel9cis_bootloader_salt != '' %}(rhel9cis_bootloader_password | grub_hash(salt=rhel9cis_bootloader_salt)) }}{% else %}{{ rhel9cis_bootloader_password_hash }}{% endif %}" # noqa template-instead-of-copy + # Used to control warning summary warn_control_list: "" warn_count: 0 From 591f0d90f4262cbc7e7bb0e55e41ed4271c1d640 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 6 Feb 2026 12:49:05 +0000 Subject: [PATCH 112/116] Updated comments for password hash and variable Signed-off-by: Mark Bolwell --- defaults/main.yml | 17 +++++++++++------ vars/main.yml | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 931ea93..7d25795 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -569,15 +569,20 @@ rhel9cis_selinux_enforce: enforcing # This variable governs whether a bootloader password should be set in '/boot/grub2/user.cfg' file. rhel9cis_set_boot_pass: false -# Either set rhel9cis_bootloader_password_hash or rhel9cis_bootloader_password and rhel9cis_bootloader_salt -# If you are not using the bootloader hash filter you can set it here if the encrypted format e.g. grub.pbkdf2.sha512.hashstring -rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret - +# 2 Options for setting the bootloader password +# 1. Set the bootloader password and salt - Reqiured the passlib python module available to the ansible controller +# or +# 2. Set the bootloader password hash +# +# Option 1: Set the bootloader password and salt - if salt is set, the password will be hashed using the salt +# Set this value to anything secure to have predictable hashes, which will prevent unnecessary changes +rhel9cis_bootloader_salt: '' # This variable will store the GRUB bootloader password to be stored in '/boot/grub2/user.cfg' file. The default value must be changed. rhel9cis_bootloader_password: 'password' # pragma: allowlist secret -# Set this value to anything secure to have predictable hashes, which will prevent unnecessary changes -rhel9cis_bootloader_salt: '' +# Option 2: Set the bootloader password hash - if the salt value is empty, the password will be set using below variable +# If you are not using the bootloader hash filter you can set it here if the encrypted format e.g. grub.pbkdf2.sha512.hashstring +rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret ## Controls 1.6.x and Controls 5.1.x # This variable governs if current Ansible role should manage system-wide crypto policy. diff --git a/vars/main.yml b/vars/main.yml index dfff3c5..17fefbd 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -24,7 +24,7 @@ rhel9cis_allowed_crypto_policies_modules: - 'NO-SSHWEAKMAC' - 'NO-WEAKMAC' -rhel9_compiled_bootloader_password: "{% if rhel9cis_bootloader_salt != '' %}(rhel9cis_bootloader_password | grub_hash(salt=rhel9cis_bootloader_salt)) }}{% else %}{{ rhel9cis_bootloader_password_hash }}{% endif %}" # noqa template-instead-of-copy +rhel9_compiled_bootloader_password: "{% if rhel9cis_bootloader_salt != '' %}{{ (rhel9cis_bootloader_password | grub_hash(salt=rhel9cis_bootloader_salt)) }}{% else %}{{ rhel9cis_bootloader_password_hash }}{% endif %}" # noqa template-instead-of-copy # Used to control warning summary warn_control_list: "" From 2863be6c02aedb4fc840ac5b0dcfcc2777bcc681 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 6 Feb 2026 14:16:29 +0000 Subject: [PATCH 113/116] tidied up comments to make it simpler Signed-off-by: Mark Bolwell --- defaults/main.yml | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 7d25795..0b29d9f 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -569,21 +569,31 @@ rhel9cis_selinux_enforce: enforcing # This variable governs whether a bootloader password should be set in '/boot/grub2/user.cfg' file. rhel9cis_set_boot_pass: false -# 2 Options for setting the bootloader password -# 1. Set the bootloader password and salt - Reqiured the passlib python module available to the ansible controller -# or -# 2. Set the bootloader password hash +################### bootloader password ##################################### # -# Option 1: Set the bootloader password and salt - if salt is set, the password will be hashed using the salt -# Set this value to anything secure to have predictable hashes, which will prevent unnecessary changes +# Two options for for setting the bootloader password +# +# Option 1: Set the bootloader password and salt – requires the passlib Python module +# to be available on the Ansible controller. +# Set this value to something secure to have predictable hashes, +# which will prevent unnecessary changes. + rhel9cis_bootloader_salt: '' -# This variable will store the GRUB bootloader password to be stored in '/boot/grub2/user.cfg' file. The default value must be changed. + +# This variable stores the GRUB bootloader password to be written +# to the '/boot/grub2/user.cfg' file. The default value must be changed. + rhel9cis_bootloader_password: 'password' # pragma: allowlist secret -# Option 2: Set the bootloader password hash - if the salt value is empty, the password will be set using below variable -# If you are not using the bootloader hash filter you can set it here if the encrypted format e.g. grub.pbkdf2.sha512.hashstring +# Option 2: Set the bootloader password hash – if the salt value is empty, +# the password will be set using the variable below. +# If you are not using the bootloader hash filter, you can set it here +# in encrypted format, e.g. grub.pbkdf2.sha512.hashstring + rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret +#################################################### + ## Controls 1.6.x and Controls 5.1.x # This variable governs if current Ansible role should manage system-wide crypto policy. rhel9cis_crypto_policy_ansiblemanaged: true From 11becb32c52b17ac13ef7f8de0408537bb506c7f Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Tue, 10 Feb 2026 16:01:05 -0500 Subject: [PATCH 114/116] QA Fixes Signed-off-by: Frederick Witty --- .ansible-lint | 1 + Changelog.md | 42 ++++++++-- README.md | 8 +- defaults/main.yml | 83 ++++++++++++------- molecule/default/converge.yml | 1 - molecule/wsl/converge.yml | 1 - tasks/audit_only.yml | 24 ++++++ tasks/main.yml | 2 +- tasks/prelim.yml | 1 + tasks/section_5/cis_5.3.2.x.yml | 4 +- tasks/section_5/cis_5.3.3.2.x.yml | 6 +- tasks/section_5/cis_5.4.2.x.yml | 2 +- tasks/section_7/cis_7.1.x.yml | 2 +- templates/etc/chrony.conf.j2 | 6 +- .../pwquality.conf.d/50-pwroot.conf.j2 | 2 +- vars/is_container.yml | 1 - vars/main.yml | 4 +- 17 files changed, 132 insertions(+), 58 deletions(-) diff --git a/.ansible-lint b/.ansible-lint index 7aa8478..8d34382 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -4,5 +4,6 @@ quiet: true skip_list: - 'package-latest' - 'risky-shell-pipe' + - 'var-naming[read-only]' use_default_rules: true verbosity: 0 diff --git a/Changelog.md b/Changelog.md index bd7162b..5e31723 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,29 @@ # Changes to RHEL9CIS +## 2.0.5 - Based on CIS v2.0.0 + +- QA Fixes +- Added rhel9cis_uses_root variable definition for 5.4.2.5 root PATH integrity task +- fixed spelling and grammar across defaults/main.yml, Changelog.md, README.md, tasks/main.yml, and vars/main.yml +- Fixed incorrect product reference in vars/main.yml comment (ubtu24cis -> rhel9cis) +- Fixed broken Changelog link in README.md (case mismatch) +- Added var-naming[read-only] to ansible-lint skip list for molecule files +- Bootloader password logic updated with salt and hash options +- Added passlib dependency documentation for bootloader password hash +- Updated company title +- Tidied up comments and variables for bootloader password +- Removed scheduled tasks +- Fixed typo thanks to Eugene @Frequentis +- Unused variable audit: wired up all unused variables, removed legacy references +- Updated chrony template to use rhel9cis_chrony_server_makestep, rtcsync, and minsources variables instead of hardcoded values +- Wired up rhel9cis_authselect_custom_profile_create toggle in authselect profile creation task +- Fixed task 5.3.3.2.7/5.3.3.2.8 mislabeling: separated password quality enforce and root enforce into correct tasks +- Wired up audit_capture_files_dir in audit_only workflow for file capture to control node +- Clarified rhel9cis_root_unlock_time documentation for commented-out alternative usage +- Removed legacy rhel9cis_rule_1_1_10 from molecule converge files and is_container.yml +- Fixed wrong variable name rhel9cis_unowned_group to rhel9cis_ungrouped_group in tasks/section_7/cis_7.1.x.yml +- Added rhel9cis_install_network_manager toggle to 3.1.2 wireless interfaces task + ## 2.0.4 - Based on CIS v2.0.0 addressed issue #419, thank you @aaronk1 @@ -17,7 +41,7 @@ Audit improvements and max-concurrent option added Benchmark version variable in audit template fixed typo thanks to @fragglexarmy #393 fixed typo thanks to @trumbaut #397 & #399 -updated auditd template to be 2.19 complaint +updated auditd template to be 2.19 compliant PR345 thanks to thulium-drake boot password hash - if used needs passlib module tidy up tags on tasks/main.yml @@ -88,7 +112,7 @@ tidy up tags on tasks/main.yml - updated controls 6.2.10-6.2.14 - audit - steps moved to prelim - - update to coipy and archive logic and variables + - update to copy and archive logic and variables - removed vars not used - updated quotes used in mode tasks - pre-commit update @@ -122,7 +146,7 @@ tidy up tags on tasks/main.yml - lint updates - .secrets updated - file mode quoted -- updated 5.6.5 thansk to feedback from S!ghs on discord community +- updated 5.6.5 thanks to feedback from S!ghs on discord community ## 1.1.1 - Based on CIS v1.0.0 @@ -154,7 +178,7 @@ tidy up tags on tasks/main.yml ## 1.0.10 - [#72](https://github.com/ansible-lockdown/RHEL9-CIS/issues/72) - - Only run check when paybook user not a superuser + - Only run check when playbook user not a superuser - fix for 5.5.3 thanks to @nrg-fv ## 1.0.9 @@ -226,7 +250,7 @@ Jan-2023 release - updated ansible minimum to 2.10 - Lint file updates and improvements -- auditd now shows diff ater initial template added +- auditd now shows diff after initial template added - many control rewritten - Many controls moved ID references - Audit updates aligned @@ -251,7 +275,7 @@ Jan-2023 release - #209 5.6.5 rewrite umask settings - #220 tidy up and align variables - #226 Thanks to Thulium-Drake - -Extended the auditd config required value for auditd space left percentage (not part of CIS Benchmark but required fopr auditd to run correctly in some cases) + -Extended the auditd config required value for auditd space left percentage (not part of CIS Benchmark but required for auditd to run correctly in some cases) - #227 thanks to OscarElits - chrony files now RH expected locations @@ -291,9 +315,9 @@ Jan-2023 release - not all controls work with rhel8 releases any longer - selinux disabled 1.6.1.4 - logrotate - 4.3.x -- updated to rhel8cis v2.0 benchamrk requirements +- updated to rhel8cis v2.0 benchmark requirements - removed iptables firewall controls (not valid on rhel9) -- added more to logrotate 4.3.x - sure to logrotate now a seperate package +- added more to logrotate 4.3.x - sure to logrotate now a separate package - grub path now standard to /boot/grub2/grub.cfg - 1.6.1.4 from rh8 removed as selinux.cfg doesnt disable selinux any longer - workflow update @@ -312,7 +336,7 @@ args: ``` - update boolean values to true/false -- 3.4.2 improved checks for p[ackage presence +- 3.4.2 improved checks for package presence - changed to assert for OS/release and ansible version ## Initial diff --git a/README.md b/README.md index 62e316f..15b5823 100644 --- a/README.md +++ b/README.md @@ -84,16 +84,16 @@ This role **will make changes to the system** which may have unintended conseque ## Coming From A Previous Release ⏪ -CIS release always contains changes, it is highly recommended to review the new references and available variables. This have changed significantly since ansible-lockdown initial release. +CIS release always contains changes, it is highly recommended to review the new references and available variables. These have changed significantly since ansible-lockdown initial release. This is now compatible with python3 if it is found to be the default interpreter. This does come with pre-requisites which it configures the system accordingly. -Further details can be seen in the [Changelog](./ChangeLog.md) +Further details can be seen in the [Changelog](./Changelog.md) --- ## Matching a security Level for CIS -It is possible to to only run level 1 or level 2 controls for CIS. +It is possible to only run level 1 or level 2 controls for CIS. This is managed using tags: - level1-server @@ -101,7 +101,7 @@ This is managed using tags: - level2-server - level2-workstation -The control found in defaults main also need to reflect this as this control the testing that takes place if you are using the audit component. +The controls found in defaults/main.yml also need to reflect this, as they control the testing that takes place if you are using the audit component. --- ## Requirements ✅ diff --git a/defaults/main.yml b/defaults/main.yml index 0b29d9f..8d5f907 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,6 +1,6 @@ --- -# defaults file for rhel9-cis +# defaults file for RHEL9-CIS # WARNING: # These values may be overridden by other vars-setting options(e.g. like the below 'container_vars_file'), as explained here: # https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable @@ -63,7 +63,7 @@ benchmark: RHEL9-CIS # System will reboot if false, can give better audit results skip_reboot: true -# default value will change to true but wont reboot if not enabled but will error +# default value will change to true but won't reboot if not enabled but will error change_requires_reboot: false ### @@ -93,7 +93,7 @@ audit_capture_files_dir: /some/location to copy to on control node # How to retrieve audit binary # Options are copy or download - detailed settings at the bottom of this file -# you will need to access to either github or the file already downloaded +# you will need access to either github or the file already downloaded get_audit_binary_method: download ## if get_audit_binary_method - copy the following needs to be updated for your environment @@ -387,7 +387,7 @@ rhel9cis_rule_5_3_3_2_6: true rhel9cis_rule_5_3_3_2_7: true rhel9cis_rule_5_3_3_2_8: true # 5.3.3.3 Configure pam_pwhistory module -# This are added as part of 5.3.2.4 using jinja2 template +# These are added as part of 5.3.2.4 using jinja2 template rhel9cis_rule_5_3_3_3_1: true rhel9cis_rule_5_3_3_3_2: true rhel9cis_rule_5_3_3_3_3: true @@ -522,7 +522,7 @@ rhel9cis_rule_7_2_9: true ## Ability to enable debug on mounts to assist in troubleshooting # Mount point changes are set based upon facts created in Prelim -# these then build the variable and options that is passed to the handler to set the mount point for the controls in section1. +# these then build the variable and options that are passed to the handler to set the mount point for the controls in section1. rhel9cis_debug_mount_data: false ## Control 1.1.2 @@ -569,9 +569,9 @@ rhel9cis_selinux_enforce: enforcing # This variable governs whether a bootloader password should be set in '/boot/grub2/user.cfg' file. rhel9cis_set_boot_pass: false -################### bootloader password ##################################### +################### bootloader password ############################################################ # -# Two options for for setting the bootloader password +# Two options for setting the bootloader password # # Option 1: Set the bootloader password and salt – requires the passlib Python module # to be available on the Ansible controller. @@ -592,7 +592,7 @@ rhel9cis_bootloader_password: 'password' # pragma: allowlist secret rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret -#################################################### +###################################################################################################### ## Controls 1.6.x and Controls 5.1.x # This variable governs if current Ansible role should manage system-wide crypto policy. @@ -614,7 +614,7 @@ rhel9cis_additional_crypto_policy_module: '' # - 1.7.1 - Ensure message of the day is configured properly # - 1.7.2 - Ensure local login warning banner is configured properly # - 1.7.3 - Ensure remote login warning banner is configured properly -# This variable stores the content for the Warning Banner(relevant for issue, issue.net, motd). +# This variable stores the content for the Warning Banner(relevant for issue, issue.net, motd). rhel9cis_warning_banner: Authorized users only. All activity may be monitored and reported. # End Banner @@ -850,7 +850,7 @@ rhel9cis_sshd_clientalivecountmax: 3 rhel9cis_sshd_clientaliveinterval: 15 ## Control 5.1.12 - disable forwarding -# By Default this will also disablex11 forwarding +# By Default this will also disable X11 forwarding # set 'yes' if x11 is required this can be changed to run in /etc/ssh/ssh_config.d/50-redhat.conf rhel9cis_sshd_x11forwarding: 'no' @@ -892,7 +892,7 @@ rhel9cis_ssh_maxsessions: 4 # This variable defines the path and file name of the sudo log file. rhel9cis_sudolog_location: "/var/log/sudo.log" -## Control 5.2.x -Ensure sudo authentication timeout is configured correctly +## Control 5.2.x - Ensure sudo authentication timeout is configured correctly # This variable sets the duration (in minutes) during which a user's authentication credentials # are cached after successfully authenticating using "sudo". This allows the user to execute # multiple commands with elevated privileges without needing to re-enter their password for each @@ -947,20 +947,37 @@ rhel9cis_authselect_default_profile_to_copy: "sssd --symlink-meta" # - 5.3.3.1.1 # This variable sets the amount of tries a password can be entered, before a user is locked. rhel9cis_pam_faillock_deny: 5 + # - 5.3.3.1.2 # This variable sets the amount of time a user will be unlocked after the max amount of -# password failures. +# password failures. rhel9cis_pam_faillock_unlock_time: 900 -# This variable represents the number of password change cycles, after which -# an user can re-use a password. -# CIS requires a value of 5 or more. -# 5.3.3.1.3 Locking even deny root or root unlock times -# rhel9cis_pamroot_lock_option options are -# even_deny_root -# root_unlock_time = {{ rhel9cis_root_unlock_time }} -rhel9cis_root_unlock_time: 60 + +##################################################################################################################### +# 5.3.3.1.3 | Ensure pam_faillock is configured - root account lockout behavior +# +# Controls how root is handled when the failed login threshold is reached. +#################### Two mutually exclusive options ################################################################# +# +# -> even_deny_root : Lock root just like any other account +# -> root_unlock_time = : Lock root but auto-unlock after seconds +# +# Note: The default value is set to 'even_deny_root' to align with the CIS Benchmark recommendation of locking root +# identically to regular users when the failed login threshold is reached. If you prefer to have root auto-unlock +# after a specified time, set 'rhel9cis_pamroot_lock_option' to "root_unlock_time = {{ rhel9cis_root_unlock_time }}" +# and adjust 'rhel9cis_root_unlock_time' as needed. +# +# Set ONE of the following: +# +# Option 1: root is locked identically to regular users when the failed login threshold is reached rhel9cis_pamroot_lock_option: even_deny_root + +# Option 2: root is locked but auto-unlocks after the specified seconds. +# Seconds before root is automatically unlocked (only used when rhel9cis_pamroot_lock_option includes root_unlock_time) +rhel9cis_root_unlock_time: 60 # rhel9cis_pamroot_lock_option: "root_unlock_time = {{ rhel9cis_root_unlock_time }}" +# +######################################################################################################################## # 5.3.3.2.1 - password difok rhel9cis_passwd_difok_file: etc/security/pwquality.conf.d/50-pwdifok.conf # pragma: allowlist secret @@ -995,12 +1012,9 @@ rhel9cis_passwd_maxsequence_value: 3 rhel9cis_passwd_dictcheck_file: etc/security/pwquality.conf.d/50-pwdictcheck.conf # pragma: allowlist secret rhel9cis_passwd_dictcheck_value: 1 -# 5.3.3.2.7 - password quality enforce +# 5.3.3.2.7 - Ensure password quality is enforced for the root user rhel9cis_passwd_quality_enforce_file: etc/security/pwquality.conf.d/50-pwquality_enforce.conf # pragma: allowlist secret rhel9cis_passwd_quality_enforce_value: 1 - -# 5.3.3.2.8 - password quality enforce for root included with 5.3.3.2.7 -rhel9cis_passwd_quality_enforce_root_file: etc/security/pwquality.conf.d/50-pwroot.conf # pragma: allowlist secret rhel9cis_passwd_quality_enforce_root_value: enforce_for_root # pragma: allowlist secret # PWhistory @@ -1038,7 +1052,7 @@ rhel9cis_force_user_maxdays: false # This can break current connecting user access rhel9cis_force_user_mindays: false -## 5.4.1.x Allow the forcing of of number of days before warning users of password expiry +## 5.4.1.x Allow the forcing of number of days before warning users of password expiry # This can break current connecting user access rhel9cis_force_user_warnage: false @@ -1048,6 +1062,15 @@ rhel9cis_force_user_warnage: false rhel9cis_futurepwchgdate_autofix: true # 5.4.2.x + +## 5.4.2.5 Root user used +# Root by default is not used unless setup by user +# The role will only run certain commands if set to true +# This allows the ability to skip tasks that may cause an issue +# With the understanding root has full access +rhel9cis_uses_root: false + +## 5.4.2.6 - Ensure root home directory permissions are 750 or more restrictive rhel9cis_root_umask: '0027' # 0027 or more restrictive ## Control 5.4.2.7 - Ensure system accounts are secured | Set nologin @@ -1064,7 +1087,7 @@ rhel9cis_shell_session_timeout: 900 # This variable specifies the path of the timeout setting file. # (TMOUT setting can be set in multiple files, but only one is required for the # rule to pass. Options are: -# - a file in `/etc/profile.d/` ending in `.s`, +# - a file in `/etc/profile.d/` ending in `.sh`, # - `/etc/profile`, or # - `/etc/bash.bashrc`. rhel9cis_shell_session_file: /etc/profile.d/tmout.sh @@ -1107,7 +1130,7 @@ rhel9cis_aide_db_file_age: 1w # If aide already setup this forces a new DB to be created rhel9cis_aide_db_recreate: false -# allows to change db file, not config need to be adjusted too +# allows changing the db file; note the config needs to be adjusted too rhel9cis_aide_db_file: /var/lib/aide/aide.db.gz ## Control 6.1.2 AIDE cron settings @@ -1138,12 +1161,12 @@ rhel9cis_aide_cron: # This variable governs the day of the month when the AIDE cronjob is run. # `*` signifies that the job is run on all days; furthermore, specific days # can be given in the range `1-31`; several days can be concatenated with a comma. - # The specified day(s) can must be in the range `1-31`. + # The specified day(s) must be in the range `1-31`. aide_day: '*' # This variable governs months when the AIDE cronjob is run. # `*` signifies that the job is run in every month; furthermore, specific months # can be given in the range `1-12`; several months can be concatenated with commas. - # The specified month(s) can must be in the range `1-12`. + # The specified month(s) must be in the range `1-12`. aide_month: '*' # This variable governs the weekdays, when the AIDE cronjob is run. # `*` signifies that the job is run on all weekdays; furthermore, specific weekdays @@ -1185,7 +1208,7 @@ rhel9cis_journald_runtimekeepfree: 100G # Current variable governs the settings for log retention(how long the log files will be kept). # Thus, it specifies the maximum time to store entries in a single journal # file before rotating to the next one. Set to 0 to turn off this feature. -# The given values is interpreted as seconds, unless suffixed with the units +# The given value is interpreted as seconds, unless suffixed with the units # `year`, `month`, `week`, `day`, `h` or `m` to override the default time unit of seconds. # Values are Xm, Xh, Xday, Xweek, Xmonth, Xyear, for example 2week is two weeks # ATTENTION: Uncomment the keyword below when values are set! diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml index 27172b2..348d0ab 100644 --- a/molecule/default/converge.yml +++ b/molecule/default/converge.yml @@ -10,7 +10,6 @@ system_is_container: true rhel9cis_selinux_disable: true rhel9cis_rule_5_2_4: false - rhel9cis_rule_1_1_10: false rhel9cis_firewall: "none" rhel9cis_rule_4_1_1_1: false rhel9cis_rule_4_1_1_2: false diff --git a/molecule/wsl/converge.yml b/molecule/wsl/converge.yml index 1725e67..daa9d18 100644 --- a/molecule/wsl/converge.yml +++ b/molecule/wsl/converge.yml @@ -11,7 +11,6 @@ rhel9cis_selinux_disable: true role_name: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}" rhel9cis_rule_5_3_4: false - rhel9cis_rule_1_1_10: false rhel9cis_rsyslog_ansiblemanaged: false rhel9cis_rule_3_4_1_3: false rhel9cis_rule_3_4_1_4: false diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index a33cb94..38b017f 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -7,6 +7,30 @@ ansible.builtin.import_tasks: file: fetch_audit_output.yml +- name: Audit_only | Capture audit files to control node + when: + - audit_only + - audit_capture_files_dir is defined + - audit_capture_files_dir | length > 0 + block: + - name: Audit_only | Ensure capture directory exists + ansible.builtin.file: + path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}" + state: directory + mode: 'u=rwx,go=rx' + become: false + delegate_to: localhost + + - name: Audit_only | Copy audit files to capture directory + ansible.builtin.fetch: + src: "{{ item }}" + dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/" + flat: true + failed_when: false + loop: + - "{{ pre_audit_outfile }}" + - "{{ post_audit_outfile }}" + - name: Audit_only | Show Audit Summary when: audit_only ansible.builtin.debug: diff --git a/tasks/main.yml b/tasks/main.yml index d6325fd..fe3b9b9 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -97,7 +97,7 @@ or (ansible_env.SUDO_USER in rhel9cis_sudoers_exclude_nopasswd_list) ) - fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} has no password set or or the user is not included in the exception list for rule 5.2.4 - It can break access" + fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} has no password set or the user is not included in the exception list for rule 5.2.4 - It can break access" success_msg: "You have a password set for the {{ ansible_env.SUDO_USER }} user or the user is included in the exception list for rule 5.2.4" - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" # noqa name[template] diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 400c88d..0b56125 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -221,6 +221,7 @@ - name: "PRELIM | PATCH | Install Network-Manager | if wireless adapter present" when: + - rhel9cis_install_network_manager - discover_wireless_adapters.rc == 0 - "'NetworkManager' not in ansible_facts.packages" ansible.builtin.package: diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index 755e737..3a53026 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -14,7 +14,9 @@ - rule_5.3.2.1 block: - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Create custom profiles" - when: rhel9cis_authselect_custom_profile_name not in prelim_authselect_profile_list.stdout + when: + - rhel9cis_authselect_custom_profile_create + - rhel9cis_authselect_custom_profile_name not in prelim_authselect_profile_list.stdout ansible.builtin.command: "/usr/bin/authselect create-profile {{ rhel9cis_authselect_custom_profile_name }} -b {{ rhel9cis_authselect_default_profile_to_copy }}" changed_when: false args: diff --git a/tasks/section_5/cis_5.3.3.2.x.yml b/tasks/section_5/cis_5.3.3.2.x.yml index e8e1530..aa2e0f8 100644 --- a/tasks/section_5/cis_5.3.3.2.x.yml +++ b/tasks/section_5/cis_5.3.3.2.x.yml @@ -340,7 +340,7 @@ - system notify: Authselect update -- name: "5.3.3.2.7 | PATCH | Ensure password quality is enforced for the root user" +- name: "5.3.3.2.7 | PATCH | Ensure password quality checking is enforced" when: rhel9cis_rule_5_3_3_2_7 tags: - level1-server @@ -350,8 +350,8 @@ - NIST800-53R5_IA-5 - pam ansible.builtin.template: - src: "{{ rhel9cis_passwd_quality_enforce_root_file }}.j2" - dest: "/{{ rhel9cis_passwd_quality_enforce_root_file }}" + src: "{{ rhel9cis_passwd_quality_enforce_file }}.j2" + dest: "/{{ rhel9cis_passwd_quality_enforce_file }}" owner: root group: root mode: 'o-rwx' diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index b291cc2..d1ba865 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -179,7 +179,7 @@ - item.stat.exists - item.stat.isdir - item.stat.pw_name != 'root' or item.stat.gr_name != 'root' or item.stat.woth or item.stat.wgrp - - (item != 'root') and (not rhel9cis_uses_root) + - (item != 'root') and (not rhel9cis_uses_root ) ansible.builtin.file: path: "{{ item.stat.path }}" state: directory diff --git a/tasks/section_7/cis_7.1.x.yml b/tasks/section_7/cis_7.1.x.yml index d958c9b..b7655aa 100644 --- a/tasks/section_7/cis_7.1.x.yml +++ b/tasks/section_7/cis_7.1.x.yml @@ -254,7 +254,7 @@ ansible.builtin.file: path: "{{ item }}" owner: "{{ rhel9cis_unowned_owner }}" - group: "{{ rhel9cis_unowned_group }}" + group: "{{ rhel9cis_ungrouped_group }}" with_items: - "{{ discovered_unowned_files_flatten }}" diff --git a/templates/etc/chrony.conf.j2 b/templates/etc/chrony.conf.j2 index cc5cd84..e09bf25 100644 --- a/templates/etc/chrony.conf.j2 +++ b/templates/etc/chrony.conf.j2 @@ -11,17 +11,19 @@ driftfile /var/lib/chrony/drift # Allow the system clock to be stepped in the first three updates # if its offset is larger than 1 second. -makestep 1.0 3 +makestep {{ rhel9cis_chrony_server_makestep }} +{% if rhel9cis_chrony_server_rtcsync %} # Enable kernel synchronization of the real-time clock (RTC). rtcsync +{% endif %} # Enable hardware timestamping on all interfaces that support it. #hwtimestamp * # Increase the minimum number of selectable sources required to adjust # the system clock. -#minsources 2 +minsources {{ rhel9cis_chrony_server_minsources }} # Allow NTP client access from local network. #allow 192.168.0.0/16 diff --git a/templates/etc/security/pwquality.conf.d/50-pwroot.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwroot.conf.j2 index 9effdae..0e51bee 100644 --- a/templates/etc/security/pwquality.conf.d/50-pwroot.conf.j2 +++ b/templates/etc/security/pwquality.conf.d/50-pwroot.conf.j2 @@ -1,3 +1,3 @@ # CIS Configurations -# 5.3.3.2.8 Ensure password quality is enforced for the root user +# 5.3.3.2.7 Ensure password quality is enforced for the root user {{ rhel9cis_passwd_quality_enforce_root_value }} diff --git a/vars/is_container.yml b/vars/is_container.yml index b49f770..bcc4cd4 100644 --- a/vars/is_container.yml +++ b/vars/is_container.yml @@ -57,7 +57,6 @@ rhel9cis_rule_1_1_6: false rhel9cis_rule_1_1_7: false rhel9cis_rule_1_1_8: false rhel9cis_rule_1_1_9: false -rhel9cis_rule_1_1_10: false # /var/log rhel9cis_rule_1_1_11: false # /var/log/audit diff --git a/vars/main.yml b/vars/main.yml index 17fefbd..c548b9a 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -41,7 +41,7 @@ gpg_key_package: "{{ ansible_facts.distribution | lower }}-gpg-keys" ## Controls 6.3.3.x - Audit template # This variable is set to true by tasks 6.3.3.1 to 6.3.3.20. As a result, the # audit settings are overwritten with the role's template. In order to exclude -# specific rules, you must set the variable of form `ubtu24cis_rule_6_3_3_x` above +# specific rules, you must set the variable of form `rhel9cis_rule_6_3_3_x` above # to `false`. update_audit_template: false @@ -52,7 +52,7 @@ update_audit_template: false # system_is_container the true. Otherwise, the default value # 'false' is left unchanged. system_is_container: false -# The filename of the existing yml file in role's 'vars/' sub-directory +# The filename of the existing yml file in role's 'vars/' sub-directory # to be used for managing the role-behavior when a container was detected: # (de)activating rules or for other tasks(e.g. disabling Selinux or a specific # firewall-type). From 71206432be548ed4993dd54308b406d0a9b311b0 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Wed, 11 Feb 2026 14:54:30 -0500 Subject: [PATCH 115/116] QA fixes and rollback of audit_only logic Signed-off-by: Frederick Witty --- defaults/main.yml | 4 ---- tasks/audit_only.yml | 24 ------------------------ tasks/prelim.yml | 6 +++--- tasks/section_3/cis_3.1.x.yml | 2 +- tasks/section_6/cis_6.2.3.x.yml | 6 +++--- templates/ansible_vars_goss.yml.j2 | 4 ++-- 6 files changed, 9 insertions(+), 37 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 8d5f907..7f83a59 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -86,9 +86,6 @@ audit_max_concurrent: 50 ## Only run Audit do not remediate audit_only: false -### As part of audit_only ### -# Path to copy the files to will create dir structure in audit_only mode -audit_capture_files_dir: /some/location to copy to on control node ############################# # How to retrieve audit binary @@ -385,7 +382,6 @@ rhel9cis_rule_5_3_3_2_4: true rhel9cis_rule_5_3_3_2_5: true rhel9cis_rule_5_3_3_2_6: true rhel9cis_rule_5_3_3_2_7: true -rhel9cis_rule_5_3_3_2_8: true # 5.3.3.3 Configure pam_pwhistory module # These are added as part of 5.3.2.4 using jinja2 template rhel9cis_rule_5_3_3_3_1: true diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index 38b017f..a33cb94 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -7,30 +7,6 @@ ansible.builtin.import_tasks: file: fetch_audit_output.yml -- name: Audit_only | Capture audit files to control node - when: - - audit_only - - audit_capture_files_dir is defined - - audit_capture_files_dir | length > 0 - block: - - name: Audit_only | Ensure capture directory exists - ansible.builtin.file: - path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}" - state: directory - mode: 'u=rwx,go=rx' - become: false - delegate_to: localhost - - - name: Audit_only | Copy audit files to capture directory - ansible.builtin.fetch: - src: "{{ item }}" - dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/" - flat: true - failed_when: false - loop: - - "{{ pre_audit_outfile }}" - - "{{ post_audit_outfile }}" - - name: Audit_only | Show Audit Summary when: audit_only ansible.builtin.debug: diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 0b56125..09e3620 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -214,15 +214,15 @@ block: - name: "PRELIM | AUDIT | Discover is wireless adapter on system" ansible.builtin.command: find /sys/class/net/*/ -type d -name wireless - register: discover_wireless_adapters + register: prelim_wireless_adapters changed_when: false check_mode: false - failed_when: discover_wireless_adapters.rc not in [ 0, 1 ] + failed_when: prelim_wireless_adapters.rc not in [ 0, 1 ] - name: "PRELIM | PATCH | Install Network-Manager | if wireless adapter present" when: - rhel9cis_install_network_manager - - discover_wireless_adapters.rc == 0 + - prelim_wireless_adapters.rc == 0 - "'NetworkManager' not in ansible_facts.packages" ansible.builtin.package: name: NetworkManager diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index 7099e55..b6bff9d 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -44,7 +44,7 @@ - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled" when: - rhel9cis_rule_3_1_2 - - discover_wireless_adapters.rc == 0 + - prelim_wireless_adapters.rc == 0 tags: - level1-server - patch diff --git a/tasks/section_6/cis_6.2.3.x.yml b/tasks/section_6/cis_6.2.3.x.yml index eaa3bd1..42c7725 100644 --- a/tasks/section_6/cis_6.2.3.x.yml +++ b/tasks/section_6/cis_6.2.3.x.yml @@ -195,7 +195,7 @@ register: discovered_rsyslog_remote_host notify: Restart rsyslog -- name: "6.2.3.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client" +- name: "6.2.3.7 | PATCH | Ensure rsyslog is not configured to receive logs from a remote client" when: rhel9cis_rule_6_2_3_7 tags: - level1-server @@ -208,7 +208,7 @@ - NIST800-53R5_AU-12 - NIST800-53R5_CM-6 block: - - name: "6.2.3.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client. | When not log host" + - name: "6.2.3.7 | PATCH | Ensure rsyslog is not configured to receive logs from a remote client. | When not log host" when: not rhel9cis_system_is_log_server ansible.builtin.replace: path: /etc/rsyslog.conf @@ -221,7 +221,7 @@ - '^(module\(load="imtcp"\))' - '^(input\(type="imtcp")' - - name: "6.2.3.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote clients. | When log host" + - name: "6.2.3.7 | PATCH | Ensure rsyslog is not configured to receive logs from a remote clients. | When log host" when: rhel9cis_system_is_log_server ansible.builtin.replace: path: /etc/rsyslog.conf diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index abc374c..a0343ee 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -206,7 +206,6 @@ rhel9cis_rule_2_4_2_1: {{ rhel9cis_rule_2_4_2_1 }} rhel9cis_rule_3_1_1: {{ rhel9cis_rule_3_1_1 }} rhel9cis_rule_3_1_2: {{ rhel9cis_rule_3_1_2 }} rhel9cis_rule_3_1_3: {{ rhel9cis_rule_3_1_3 }} -rhel9cis_ipv6_disable_method: {{ rhel9cis_ipv6_disable_method }} ## Network Kernel Modules rhel9cis_rule_3_2_1: {{ rhel9cis_rule_3_2_1 }} @@ -293,7 +292,6 @@ rhel9cis_rule_5_3_3_2_4: {{ rhel9cis_rule_5_3_3_2_4 }} rhel9cis_rule_5_3_3_2_5: {{ rhel9cis_rule_5_3_3_2_5 }} rhel9cis_rule_5_3_3_2_6: {{ rhel9cis_rule_5_3_3_2_6 }} rhel9cis_rule_5_3_3_2_7: {{ rhel9cis_rule_5_3_3_2_7 }} -rhel9cis_rule_5_3_3_2_8: {{ rhel9cis_rule_5_3_3_2_8 }} # 5.3.3.3 Configure pam_pwhistory module # This are added as part of 5.3.2.4 using jinja2 template rhel9cis_rule_5_3_3_3_1: {{ rhel9cis_rule_5_3_3_3_1 }} @@ -532,6 +530,8 @@ rhel9cis_bluetooth_mask: {{ rhel9cis_bluetooth_mask }} ## 3.1 IPv6 requirement toggle # This variable governs whether ipv6 is enabled or disabled. rhel9cis_ipv6_required: {{ rhel9cis_ipv6_required }} +# rhel9cis_ipv6_disable defines the method of disabling IPv6, sysctl vs kernel +rhel9cis_ipv6_disable_method: {{ rhel9cis_ipv6_disable_method }} # 3.3 System network parameters (host only OR host and router) # This variable governs whether specific CIS rules From f413385208f269285ab509c29e65d1e9d43a864b Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Wed, 11 Feb 2026 15:39:59 -0500 Subject: [PATCH 116/116] Update .j2 branding Signed-off-by: Frederick Witty --- Changelog.md | 1 + meta/main.yml | 6 +++--- templates/audit/98_auditd_exception.rules.j2 | 4 +--- templates/audit/99_auditd.rules.j2 | 4 +--- templates/etc/aide.conf.d/crypt_audit_procs.conf.j2 | 1 + templates/etc/ansible/compliance_facts.j2 | 4 +--- templates/etc/chrony.conf.j2 | 2 +- templates/etc/cron.d/aide.cron.j2 | 4 +--- .../etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 | 1 + .../etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 | 1 + .../etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 | 1 + .../policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 | 1 + .../policies/modules/NO-SSHWEAKMACS.pmod.j2 | 1 + .../crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 | 1 + templates/etc/dconf/db/00-automount_lock.j2 | 4 +--- templates/etc/dconf/db/00-autorun_lock.j2 | 4 +--- templates/etc/dconf/db/00-media-automount.j2 | 4 +--- templates/etc/dconf/db/00-media-autorun.j2 | 4 +--- templates/etc/dconf/db/00-screensaver.j2 | 4 +--- templates/etc/dconf/db/00-screensaver_lock.j2 | 4 +--- templates/etc/dconf/db/gdm.d/01-banner-message.j2 | 4 +--- templates/etc/logrotate.d/rsyslog_log.j2 | 1 + templates/etc/modprobe.d/modprobe.conf.j2 | 6 ++---- .../etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 | 1 + .../etc/security/pwquality.conf.d/50-pwdictcheck.conf.j2 | 1 + templates/etc/security/pwquality.conf.d/50-pwdifok.conf.j2 | 1 + .../etc/security/pwquality.conf.d/50-pwlength.conf.j2 | 1 + .../etc/security/pwquality.conf.d/50-pwmaxsequence.conf.j2 | 1 + .../security/pwquality.conf.d/50-pwquality_enforce.conf.j2 | 1 + .../etc/security/pwquality.conf.d/50-pwrepeat.conf.j2 | 1 + templates/etc/security/pwquality.conf.d/50-pwroot.conf.j2 | 1 + templates/etc/sysctl.d/60-disable_ipv6.conf.j2 | 3 ++- templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 | 3 ++- templates/etc/sysctl.d/60-netipv4_sysctl.conf.j2 | 3 ++- templates/etc/sysctl.d/60-netipv6_sysctl.conf.j2 | 3 ++- .../etc/systemd/journald.conf.d/forwardtosyslog.conf.j2 | 2 +- templates/etc/systemd/journald.conf.d/rotation.conf.j2 | 2 +- templates/etc/systemd/journald.conf.d/storage.conf.j2 | 2 +- templates/etc/systemd/system/tmp.mount.j2 | 3 ++- vars/main.yml | 7 ++++++- 40 files changed, 53 insertions(+), 50 deletions(-) diff --git a/Changelog.md b/Changelog.md index 5e31723..b5b160c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,6 +3,7 @@ ## 2.0.5 - Based on CIS v2.0.0 - QA Fixes +- .j2 Branding Update - Added rhel9cis_uses_root variable definition for 5.4.2.5 root PATH integrity task - fixed spelling and grammar across defaults/main.yml, Changelog.md, README.md, tasks/main.yml, and vars/main.yml - Fixed incorrect product reference in vars/main.yml comment (ubtu24cis -> rhel9cis) diff --git a/meta/main.yml b/meta/main.yml index 8f8b65f..9418c84 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,11 +1,11 @@ --- galaxy_info: - author: "MindPoint Group" + author: "Ansible-Lockdown" description: "Apply the RHEL 9 CIS" - company: "MindPoint Group" + company: "MindPoint Group - A Tyto Athene Company" license: MIT role_name: rhel9_cis - namespace: mindpointgroup + namespace: ansible-lockdown min_ansible_version: 2.10.1 platforms: - name: EL diff --git a/templates/audit/98_auditd_exception.rules.j2 b/templates/audit/98_auditd_exception.rules.j2 index 1bec877..d3e394a 100644 --- a/templates/audit/98_auditd_exception.rules.j2 +++ b/templates/audit/98_auditd_exception.rules.j2 @@ -1,6 +1,4 @@ -## Ansible controlled file -# Added as part of ansible-lockdown CIS baseline -# provided by {{ company_title }} +{{ file_managed_by_ansible }} ### YOUR CHANGES WILL BE LOST! # This file contains users whose actions are not logged by auditd diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 0a0cadf..af65935 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -1,6 +1,4 @@ -## Ansible controlled file -# Added as part of ansible-lockdown CIS baseline -# provided by {{ company_title }} +{{ file_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 diff --git a/templates/etc/aide.conf.d/crypt_audit_procs.conf.j2 b/templates/etc/aide.conf.d/crypt_audit_procs.conf.j2 index fb12b29..b28aea1 100644 --- a/templates/etc/aide.conf.d/crypt_audit_procs.conf.j2 +++ b/templates/etc/aide.conf.d/crypt_audit_procs.conf.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # Audit Tools /sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512 /sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512 diff --git a/templates/etc/ansible/compliance_facts.j2 b/templates/etc/ansible/compliance_facts.j2 index 896c159..0da1b18 100644 --- a/templates/etc/ansible/compliance_facts.j2 +++ b/templates/etc/ansible/compliance_facts.j2 @@ -1,6 +1,4 @@ -# CIS Hardening Carried out -# Added as part of ansible-lockdown CIS baseline -# provided by {{ company_title }} +{{ file_managed_by_ansible }} [lockdown_details] # Benchmark release diff --git a/templates/etc/chrony.conf.j2 b/templates/etc/chrony.conf.j2 index e09bf25..671e2f0 100644 --- a/templates/etc/chrony.conf.j2 +++ b/templates/etc/chrony.conf.j2 @@ -1,4 +1,4 @@ -{{ ansible_managed | comment }} +{{ file_managed_by_ansible }} # Use public servers from the pool.ntp.org project. # Please consider joining the pool (http://www.pool.ntp.org/join.html). diff --git a/templates/etc/cron.d/aide.cron.j2 b/templates/etc/cron.d/aide.cron.j2 index 15ea95f..df0b1a5 100644 --- a/templates/etc/cron.d/aide.cron.j2 +++ b/templates/etc/cron.d/aide.cron.j2 @@ -1,7 +1,5 @@ +{{ file_managed_by_ansible }} # Run AIDE integrity check -## Ansible controlled file -# Added as part of ansible-lockdown CIS baseline -# provided by {{ company_title }} ### YOUR CHANGES WILL BE LOST! # CIS 1.3.2 diff --git a/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 index fd6eaff..7b907ab 100644 --- a/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 +++ b/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # This is a subpolicy dropping the SHA1 hash and signature support # Carried out as part of CIS Benchmark rule 1.6.3 diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 index 9092036..3619008 100644 --- a/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # This is a subpolicy to disable all CBC mode ciphers # for the SSH protocol (libssh and OpenSSH) # Carried out as part of CIS Benchmark rule 1.6.5 diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 index cebc2ad..570048c 100644 --- a/templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # This is a subpolicy to disable Encrypt then MAC # for the SSH protocol (libssh and OpenSSH) # Carried out as part of CIS Benchmark rule 1.6.7 diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 index 393cf88..f03cd05 100644 --- a/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # This is a subpolicy to disable weak ciphers # for the SSH protocol (libssh and OpenSSH) # Carried out as part of CIS Benchmark rules combined 1.6.6 and 5.1.4 diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKMACS.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKMACS.pmod.j2 index f040399..25e2336 100644 --- a/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKMACS.pmod.j2 +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKMACS.pmod.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # This is a subpolicy to disable weak macs # Carried out as part of CIS Benchmark control 5.1.6 diff --git a/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 index 0020e6d..984106a 100644 --- a/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 +++ b/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # This is a subpolicy to disable weak macs # Carried out as part of CIS Benchmark rule 1.6.4 diff --git a/templates/etc/dconf/db/00-automount_lock.j2 b/templates/etc/dconf/db/00-automount_lock.j2 index f6ac336..f3c3b74 100644 --- a/templates/etc/dconf/db/00-automount_lock.j2 +++ b/templates/etc/dconf/db/00-automount_lock.j2 @@ -1,6 +1,4 @@ -## Ansible controlled file -# Added as part of ansible-lockdown CIS baseline -# provided by {{ company_title }} +{{ file_managed_by_ansible }} # Lock desktop media-handling automount setting /org/gnome/desktop/media-handling/automount diff --git a/templates/etc/dconf/db/00-autorun_lock.j2 b/templates/etc/dconf/db/00-autorun_lock.j2 index 17dcd56..a09aca5 100644 --- a/templates/etc/dconf/db/00-autorun_lock.j2 +++ b/templates/etc/dconf/db/00-autorun_lock.j2 @@ -1,6 +1,4 @@ -## Ansible controlled file -# Added as part of ansible-lockdown CIS baseline -# provided by {{ company_title }} +{{ file_managed_by_ansible }} # Lock desktop media-handling settings /org/gnome/desktop/media-handling/autorun-never diff --git a/templates/etc/dconf/db/00-media-automount.j2 b/templates/etc/dconf/db/00-media-automount.j2 index 84f086d..f81aaea 100644 --- a/templates/etc/dconf/db/00-media-automount.j2 +++ b/templates/etc/dconf/db/00-media-automount.j2 @@ -1,6 +1,4 @@ -## Ansible controlled file -# Added as part of ansible-lockdown CIS baseline -# provided by {{ company_title }} +{{ file_managed_by_ansible }} [org/gnome/desktop/media-handling] automount=false diff --git a/templates/etc/dconf/db/00-media-autorun.j2 b/templates/etc/dconf/db/00-media-autorun.j2 index 528f1be..6928d80 100644 --- a/templates/etc/dconf/db/00-media-autorun.j2 +++ b/templates/etc/dconf/db/00-media-autorun.j2 @@ -1,6 +1,4 @@ -## Ansible controlled file -# Added as part of ansible-lockdown CIS baseline -# provided by {{ company_title }} +{{ file_managed_by_ansible }} [org/gnome/desktop/media-handling] autorun-never=true diff --git a/templates/etc/dconf/db/00-screensaver.j2 b/templates/etc/dconf/db/00-screensaver.j2 index a6c6894..1445dcc 100644 --- a/templates/etc/dconf/db/00-screensaver.j2 +++ b/templates/etc/dconf/db/00-screensaver.j2 @@ -1,6 +1,4 @@ -## Ansible controlled file -# Added as part of ansible-lockdown CIS baseline -# provided by {{ company_title }} +{{ file_managed_by_ansible }} # Specify the dconf path [org/gnome/desktop/session] diff --git a/templates/etc/dconf/db/00-screensaver_lock.j2 b/templates/etc/dconf/db/00-screensaver_lock.j2 index ab8d41d..eafc95e 100644 --- a/templates/etc/dconf/db/00-screensaver_lock.j2 +++ b/templates/etc/dconf/db/00-screensaver_lock.j2 @@ -1,6 +1,4 @@ -## Ansible controlled file -# Added as part of ansible-lockdown CIS baseline -# provided by {{ company_title }} +{{ file_managed_by_ansible }} # Lock desktop screensaver idle-delay setting /org/gnome/desktop/session/idle-delay diff --git a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 index b5fac22..54562d2 100644 --- a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 +++ b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 @@ -1,6 +1,4 @@ -## Ansible controlled file -# Added as part of ansible-lockdown CIS baseline -# provided by {{ company_title }} +{{ file_managed_by_ansible }} [org/gnome/login-screen] banner-message-enable=true diff --git a/templates/etc/logrotate.d/rsyslog_log.j2 b/templates/etc/logrotate.d/rsyslog_log.j2 index 8acb53e..d9aa2a7 100644 --- a/templates/etc/logrotate.d/rsyslog_log.j2 +++ b/templates/etc/logrotate.d/rsyslog_log.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} /var/log/rsyslog/*.log { {{ rhel9cis_rsyslog_logrotate_rotated_when }} rotate {{ rhel9cis_rsyslog_logrotate_rotatation_keep }} diff --git a/templates/etc/modprobe.d/modprobe.conf.j2 b/templates/etc/modprobe.d/modprobe.conf.j2 index 77b8cd5..6c3d7d8 100644 --- a/templates/etc/modprobe.d/modprobe.conf.j2 +++ b/templates/etc/modprobe.d/modprobe.conf.j2 @@ -1,6 +1,4 @@ -# 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! +{{ file_managed_by_ansible }} +## YOUR CHANGES WILL BE LOST! install {{ item }} /bin/true diff --git a/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 index c223c84..d8cdb67 100644 --- a/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 +++ b/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # CIS Configurations # 5.3.3.2.3 Ensure password complexity is configured {% if rhel9cis_passwd_complex_option == 'minclass' %} # pragma: allowlist secret diff --git a/templates/etc/security/pwquality.conf.d/50-pwdictcheck.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwdictcheck.conf.j2 index 09b6ee3..e7cd0e0 100644 --- a/templates/etc/security/pwquality.conf.d/50-pwdictcheck.conf.j2 +++ b/templates/etc/security/pwquality.conf.d/50-pwdictcheck.conf.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # CIS Configurations # 5.3.3.2.6 Ensure password dictionary check is enabled dictcheck = {{ rhel9cis_passwd_dictcheck_value }} diff --git a/templates/etc/security/pwquality.conf.d/50-pwdifok.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwdifok.conf.j2 index 2e8ae2d..d69120a 100644 --- a/templates/etc/security/pwquality.conf.d/50-pwdifok.conf.j2 +++ b/templates/etc/security/pwquality.conf.d/50-pwdifok.conf.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # CIS Configurations # 5.3.3.2.1 Ensure password number of changed characters is configured difok = {{ rhel9cis_passwd_difok_value }} diff --git a/templates/etc/security/pwquality.conf.d/50-pwlength.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwlength.conf.j2 index 9e874ee..0f893ac 100644 --- a/templates/etc/security/pwquality.conf.d/50-pwlength.conf.j2 +++ b/templates/etc/security/pwquality.conf.d/50-pwlength.conf.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # CIS Configurations # 5.3.3.2.2 Ensure minimum password length is configured minlen = {{ rhel9cis_passwd_minlen_value }} diff --git a/templates/etc/security/pwquality.conf.d/50-pwmaxsequence.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwmaxsequence.conf.j2 index a561fec..d200904 100644 --- a/templates/etc/security/pwquality.conf.d/50-pwmaxsequence.conf.j2 +++ b/templates/etc/security/pwquality.conf.d/50-pwmaxsequence.conf.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # CIS Configurations # 5.3.3.2.5 Ensure password maximum sequential characters is configured maxsequence = {{ rhel9cis_passwd_maxsequence_value }} diff --git a/templates/etc/security/pwquality.conf.d/50-pwquality_enforce.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwquality_enforce.conf.j2 index 6fea8db..c8fff7e 100644 --- a/templates/etc/security/pwquality.conf.d/50-pwquality_enforce.conf.j2 +++ b/templates/etc/security/pwquality.conf.d/50-pwquality_enforce.conf.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # CIS Configurations # 5.3.3.2.7 Ensure password quality checking is enforced enforcing = {{ rhel9cis_passwd_quality_enforce_value }} diff --git a/templates/etc/security/pwquality.conf.d/50-pwrepeat.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwrepeat.conf.j2 index 28b8dde..0b2c592 100644 --- a/templates/etc/security/pwquality.conf.d/50-pwrepeat.conf.j2 +++ b/templates/etc/security/pwquality.conf.d/50-pwrepeat.conf.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # CIS Configurations # 5.3.3.2.4 Ensure password same consecutive characters is configured maxrepeat = {{ rhel9cis_passwd_maxrepeat_value }} diff --git a/templates/etc/security/pwquality.conf.d/50-pwroot.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwroot.conf.j2 index 0e51bee..243d7fb 100644 --- a/templates/etc/security/pwquality.conf.d/50-pwroot.conf.j2 +++ b/templates/etc/security/pwquality.conf.d/50-pwroot.conf.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # CIS Configurations # 5.3.3.2.7 Ensure password quality is enforced for the root user {{ rhel9cis_passwd_quality_enforce_root_value }} diff --git a/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 b/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 index b4b5318..dfca519 100644 --- a/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 +++ b/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 @@ -1,4 +1,5 @@ -## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! +{{ file_managed_by_ansible }} +## YOUR CHANGES WILL BE LOST! # IPv6 disable {% if rhel9cis_rule_3_1_1 and not 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 11a93f2..12901dc 100644 --- a/templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 +++ b/templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 @@ -1,4 +1,5 @@ -## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! +{{ file_managed_by_ansible }} +## YOUR CHANGES WILL BE LOST! {% if rhel9cis_rule_1_5_1 %} # Adress space randomise diff --git a/templates/etc/sysctl.d/60-netipv4_sysctl.conf.j2 b/templates/etc/sysctl.d/60-netipv4_sysctl.conf.j2 index 336071c..8d27e8f 100644 --- a/templates/etc/sysctl.d/60-netipv4_sysctl.conf.j2 +++ b/templates/etc/sysctl.d/60-netipv4_sysctl.conf.j2 @@ -1,4 +1,5 @@ -## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! +{{ file_managed_by_ansible }} +## YOUR CHANGES WILL BE LOST! # IPv4 Network sysctl {% if rhel9cis_rule_3_3_1 %} diff --git a/templates/etc/sysctl.d/60-netipv6_sysctl.conf.j2 b/templates/etc/sysctl.d/60-netipv6_sysctl.conf.j2 index 07e045d..3ef53f4 100644 --- a/templates/etc/sysctl.d/60-netipv6_sysctl.conf.j2 +++ b/templates/etc/sysctl.d/60-netipv6_sysctl.conf.j2 @@ -1,4 +1,5 @@ -## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! +{{ file_managed_by_ansible }} +## YOUR CHANGES WILL BE LOST! # IPv6 Network sysctl {% if rhel9cis_ipv6_required %} diff --git a/templates/etc/systemd/journald.conf.d/forwardtosyslog.conf.j2 b/templates/etc/systemd/journald.conf.d/forwardtosyslog.conf.j2 index 3b00ce1..682cdd5 100644 --- a/templates/etc/systemd/journald.conf.d/forwardtosyslog.conf.j2 +++ b/templates/etc/systemd/journald.conf.d/forwardtosyslog.conf.j2 @@ -1,4 +1,4 @@ -# File created for CIS benchmark +{{ file_managed_by_ansible }} # CIS rule 6_2_2_2 [Journal] ForwardToSyslog=no diff --git a/templates/etc/systemd/journald.conf.d/rotation.conf.j2 b/templates/etc/systemd/journald.conf.d/rotation.conf.j2 index 07eedba..4a3174b 100644 --- a/templates/etc/systemd/journald.conf.d/rotation.conf.j2 +++ b/templates/etc/systemd/journald.conf.d/rotation.conf.j2 @@ -1,4 +1,4 @@ -# File created for CIS benchmark +{{ file_managed_by_ansible }} # CIS rule 6_2_1_3 [Journal] SystemMaxUse={{ rhel9cis_journald_systemmaxuse }} diff --git a/templates/etc/systemd/journald.conf.d/storage.conf.j2 b/templates/etc/systemd/journald.conf.d/storage.conf.j2 index 214f9db..5e5726d 100644 --- a/templates/etc/systemd/journald.conf.d/storage.conf.j2 +++ b/templates/etc/systemd/journald.conf.d/storage.conf.j2 @@ -1,4 +1,4 @@ -# File created for CIS benchmark +{{ file_managed_by_ansible }} [Journal] {% if rhel9cis_rule_6_2_2_3 %} # Set compress CIS rule 6_2_2_3 diff --git a/templates/etc/systemd/system/tmp.mount.j2 b/templates/etc/systemd/system/tmp.mount.j2 index 7f64547..245102f 100644 --- a/templates/etc/systemd/system/tmp.mount.j2 +++ b/templates/etc/systemd/system/tmp.mount.j2 @@ -1,3 +1,4 @@ +{{ file_managed_by_ansible }} # SPDX-License-Identifier: LGPL-2.1+ # # This file is part of systemd. @@ -7,7 +8,7 @@ # 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! +## YOUR CHANGED WILL BE LOST! [Unit] Description=Temporary Directory (/tmp) diff --git a/vars/main.yml b/vars/main.yml index c548b9a..2225042 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -77,4 +77,9 @@ audit_bins: - /sbin/auditd - /sbin/augenrules -company_title: 'Mindpoint Group - A Tyto Athene Company' +company_title: 'MindPoint Group - A Tyto Athene Company' + +file_managed_by_ansible: |- + # File managed by ansible as part of {{ benchmark }} benchmark + # As part of Ansible-lockdown + # Provided by {{ company_title }}