From 683177e46fd0cfc8a3e4a4a98adbc3a4948d6b7f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 31 Mar 2025 12:33:56 +0100 Subject: [PATCH 01/10] issue #305 addressed Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.2.1.x.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tasks/section_6/cis_6.2.1.x.yml b/tasks/section_6/cis_6.2.1.x.yml index 3afa31c..2d861e8 100644 --- a/tasks/section_6/cis_6.2.1.x.yml +++ b/tasks/section_6/cis_6.2.1.x.yml @@ -96,15 +96,21 @@ - rule_6.2.1.4 block: - name: "6.2.1.4 | PATCH | Ensure only one logging system is in use | when rsyslog" - when: rhel9cis_syslog == "rsyslog" + when: + - rhel9cis_syslog == "rsyslog" + - "'systemd-journald' in ansible_facts.packages" ansible.builtin.systemd: name: systemd-journald state: stopped enabled: false - name: "6.2.1.4 | PATCH | Ensure only one logging system is in use | when journald" - when: rhel9cis_syslog == "journald" + when: + - rhel9cis_syslog == "journald" + - "'rsyslog' in ansible_facts.packages" ansible.builtin.systemd: name: rsyslog state: stopped enabled: false + register: discovered_rsyslog_service + From b616f70d862527715ffd6d0092a87efe3b3a1512 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 31 Mar 2025 12:35:07 +0100 Subject: [PATCH 02/10] addressed #306 Signed-off-by: Mark Bolwell --- tasks/section_2/cis_2.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index e49e733..98ede95 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -657,7 +657,7 @@ - postfix - NIST800-53R5_CM-7 - rule_2.1.21 - notify: Restart_postfix + notify: Restart postfix ansible.builtin.lineinfile: path: /etc/postfix/main.cf regexp: "^(#)?inet_interfaces" From cedf510b94abb6220981d87b29cb349f5418f5c8 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 31 Mar 2025 12:36:27 +0100 Subject: [PATCH 03/10] addressed #309 Signed-off-by: Mark Bolwell --- tasks/section_2/cis_2.1.x.yml | 40 +++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index 98ede95..28e372d 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -25,7 +25,7 @@ when: - not rhel9cis_autofs_services - rhel9cis_autofs_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: autofs enabled: false @@ -57,7 +57,7 @@ when: - not rhel9cis_avahi_server - rhel9cis_avahi_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: "{{ item }}" enabled: false @@ -90,7 +90,7 @@ when: - not rhel9cis_dhcp_server - rhel9cis_dhcp_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: "{{ item }}" enabled: false @@ -123,7 +123,7 @@ when: - not rhel9cis_dns_server - rhel9cis_dns_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: named.service enabled: false @@ -153,7 +153,7 @@ when: - not rhel9cis_dnsmasq_server - rhel9cis_dnsmasq_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: dnsmasq.service enabled: false @@ -184,7 +184,7 @@ when: - not rhel9cis_samba_server - rhel9cis_samba_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: smb.service enabled: false @@ -215,7 +215,7 @@ when: - not rhel9cis_ftp_server - rhel9cis_ftp_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: vsftpd.service enabled: false @@ -249,7 +249,7 @@ when: - not rhel9cis_message_server - rhel9cis_message_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: "{{ item }}" enabled: false @@ -285,7 +285,7 @@ when: - not rhel9cis_nfs_server - rhel9cis_nfs_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: nfs-server.service enabled: false @@ -302,7 +302,7 @@ - nis - NIST800-53R5_CM-7 - rule_2.1.10 - notify: Systemd_daemon_reload + notify: Systemd daemon reload block: - name: "2.1.10 | PATCH | Ensure nis server services are not in use | Remove package" when: @@ -344,7 +344,7 @@ when: - not rhel9cis_print_server - rhel9cis_print_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: "{{ item }}" enabled: false @@ -378,7 +378,7 @@ when: - not rhel9cis_rpc_server - rhel9cis_rpc_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: "{{ item }}" enabled: false @@ -412,7 +412,7 @@ when: - not rhel9cis_rsync_server - rhel9cis_rsync_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: "{{ item }}" enabled: false @@ -445,7 +445,7 @@ when: - not rhel9cis_snmp_server - rhel9cis_snmp_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: snmpd.service enabled: false @@ -476,7 +476,7 @@ when: - not rhel9cis_telnet_server - rhel9cis_telnet_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: telnet.socket enabled: false @@ -506,7 +506,7 @@ when: - not rhel9cis_tftp_server - rhel9cis_tftp_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: "{{ item }}" enabled: false @@ -540,7 +540,7 @@ when: - not rhel9cis_squid_server - rhel9cis_squid_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: squid.service enabled: false @@ -580,7 +580,7 @@ when: - not rhel9cis_httpd_server - rhel9cis_httpd_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: httpd.service enabled: false @@ -591,7 +591,7 @@ when: - not rhel9cis_nginx_server - rhel9cis_nginx_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: ngnix.service enabled: false @@ -621,7 +621,7 @@ when: - not rhel9cis_xinetd_server - rhel9cis_xinetd_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: xinetd.service enabled: false From 7b1c8e9ef0f3654ef65e86606508ceca9d0e4b24 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 31 Mar 2025 12:37:58 +0100 Subject: [PATCH 04/10] additional fix for #309 Signed-off-by: Mark Bolwell --- tasks/section_3/cis_3.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index e8934d4..68a66de 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -86,7 +86,7 @@ when: - not rhel9cis_bluetooth_service - rhel9cis_bluetooth_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: bluetooth.service enabled: false From 82904557c7443a584988c5badf9bfa9f1550befd Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 31 Mar 2025 12:38:51 +0100 Subject: [PATCH 05/10] 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 576531e9862c596da454e1283cdd549cf6806827 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 31 Mar 2025 14:50:40 +0100 Subject: [PATCH 06/10] fetch audit and compliance facts added Signed-off-by: Mark Bolwell --- defaults/main.yml | 17 +++++++++ tasks/fetch_audit_output.yml | 46 +++++++++++++++++++++++ tasks/main.yml | 32 ++++++++++++++++ templates/etc/ansible/compliance_facts.j2 | 39 +++++++++++++++++++ 4 files changed, 134 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..f2bd882 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..ccd6c1d 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -209,11 +209,43 @@ - name: "Run post_remediation audit" when: run_audit + tags: always 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 + tags: always ansible.builtin.debug: msg: "{{ audit_results.split('\n') }}" diff --git a/templates/etc/ansible/compliance_facts.j2 b/templates/etc/ansible/compliance_facts.j2 new file mode 100644 index 0000000..1e7d896 --- /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 + +[Benchmark_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 %} + +[Benchmark_Audit_Details] +{% if run_audit %} +# Audit run +audit_file_location_local = {{ audit_log_dir }} +{% if not audit_only %} +audit_summary = {{ post_audit_results }} +{% endif %} +{% if fetch_audit_output %} +audit_files_location_central = {{ audit_output_destination }} +{% endif %} +{% endif %} From 04666c219c9a1eb751419852ba752c355b3040c1 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 31 Mar 2025 15:13:46 +0100 Subject: [PATCH 07/10] Added for #288 ansible_facts Signed-off-by: Mark Bolwell --- templates/etc/ansible/compliance_facts.j2 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/etc/ansible/compliance_facts.j2 b/templates/etc/ansible/compliance_facts.j2 index 1e7d896..ffa366c 100644 --- a/templates/etc/ansible/compliance_facts.j2 +++ b/templates/etc/ansible/compliance_facts.j2 @@ -2,7 +2,7 @@ # Added as part of ansible-lockdown CIS baseline # provided by Mindpoint Group - A Tyto Athene Company -[Benchmark_Details] +[benchmark_details] # Benchmark release Benchmark_release = CIS-{{ benchmark_version }} Benchmark_run_date = {{ '%Y-%m-%d - %H:%M:%S' | ansible.builtin.strftime }} @@ -26,14 +26,14 @@ Level_2_workstation_tag_run = true {% endif %} {% endif %} -[Benchmark_Audit_Details] +[benchmark_audit_details] {% if run_audit %} # Audit run -audit_file_location_local = {{ audit_log_dir }} +audit_file_local_location = {{ audit_log_dir }} {% if not audit_only %} audit_summary = {{ post_audit_results }} {% endif %} {% if fetch_audit_output %} -audit_files_location_central = {{ audit_output_destination }} +audit_files_centralized_location = {{ audit_output_destination }} {% endif %} {% endif %} From fc2e153ce90350576e8ae83b91893edca0bc9ddf Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 1 Apr 2025 07:55:08 +0100 Subject: [PATCH 08/10] updated section naming Signed-off-by: Mark Bolwell --- templates/etc/ansible/compliance_facts.j2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/etc/ansible/compliance_facts.j2 b/templates/etc/ansible/compliance_facts.j2 index ffa366c..f313bec 100644 --- a/templates/etc/ansible/compliance_facts.j2 +++ b/templates/etc/ansible/compliance_facts.j2 @@ -2,7 +2,7 @@ # Added as part of ansible-lockdown CIS baseline # provided by Mindpoint Group - A Tyto Athene Company -[benchmark_details] +[lockdown_details] # Benchmark release Benchmark_release = CIS-{{ benchmark_version }} Benchmark_run_date = {{ '%Y-%m-%d - %H:%M:%S' | ansible.builtin.strftime }} @@ -26,7 +26,7 @@ Level_2_workstation_tag_run = true {% endif %} {% endif %} -[benchmark_audit_details] +[lockdown_audit_details] {% if run_audit %} # Audit run audit_file_local_location = {{ audit_log_dir }} From 9bbf5b7a81d8a4db1048cc055318363df4c3c9cb Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 1 Apr 2025 08:08:28 +0100 Subject: [PATCH 09/10] updated var name to remove capital Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 +- tasks/main.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index f2bd882..32c4679 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -34,7 +34,7 @@ rhel9cis_level_1: true rhel9cis_level_2: true # Create managed not custom local_facts files -Create_benchmark_facts: true +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 diff --git a/tasks/main.yml b/tasks/main.yml index ccd6c1d..57fd8fd 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -214,7 +214,7 @@ file: post_remediation_audit.yml - name: Add ansible file showing Benchmark and levels applied - when: Create_benchmark_facts + when: create_benchmark_facts tags: - always - benchmark From bd425a068d4b23e16d8793a1fb94a205323bd33c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 1 Apr 2025 08:14:02 +0100 Subject: [PATCH 10/10] lint updates Signed-off-by: Mark Bolwell --- tasks/main.yml | 6 +++--- tasks/section_1/cis_1.4.x.yml | 2 +- tasks/section_6/cis_6.2.1.x.yml | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index 57fd8fd..00281da 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 @@ -216,8 +216,8 @@ - name: Add ansible file showing Benchmark and levels applied when: create_benchmark_facts tags: - - always - - benchmark + - always + - benchmark block: - name: Create ansible facts directory ansible.builtin.file: 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" diff --git a/tasks/section_6/cis_6.2.1.x.yml b/tasks/section_6/cis_6.2.1.x.yml index 2d861e8..fa75880 100644 --- a/tasks/section_6/cis_6.2.1.x.yml +++ b/tasks/section_6/cis_6.2.1.x.yml @@ -113,4 +113,3 @@ state: stopped enabled: false register: discovered_rsyslog_service -