From a1126618a7b22475921834e166d339707ab04e3b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 10:52:32 +0100 Subject: [PATCH 1/8] 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 2/8] 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 3/8] 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 4/8] 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 5/8] 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 6/8] 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 7/8] 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 8/8] 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