From 636eb4d1e3cf81a02a023db6683ac114a65326e6 Mon Sep 17 00:00:00 2001 From: Lars Erik Wik Date: Tue, 10 Mar 2026 11:53:12 +0100 Subject: [PATCH 1/3] Fix sshd hardening being overridden by drop-in configs On Ubuntu, /etc/ssh/sshd_config includes drop-in files from sshd_config.d/ near the top, and OpenSSH uses first-match-wins. The previous policy only edited the main sshd_config, so drop-ins like 50-cloud-init.conf setting PasswordAuthentication yes took precedence. Changes: - Add sshd_hardening_directives slist to avoid repeating directive names - Comment out insecure values recursively across /etc/ssh (main config and all drop-ins), not just sshd_config - Prepend hardening directives to the top of sshd_config, before the Include directive, so they take precedence over any drop-in Ticket: ENT-13766 Signed-off-by: Lars Erik Wik --- ci/cfengine-build-host-setup.cf | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/ci/cfengine-build-host-setup.cf b/ci/cfengine-build-host-setup.cf index c70b48d7f..25ac72227 100644 --- a/ci/cfengine-build-host-setup.cf +++ b/ci/cfengine-build-host-setup.cf @@ -182,6 +182,13 @@ bundle agent cfengine_build_host_setup vars: "suse_users_and_groups" slist => { "daemon", "bin", "sys" }; + "sshd_hardening_directives" slist => { + "PermitRootLogin", + "PasswordAuthentication", + "KbdInteractiveAuthentication", + "ChallengeResponseAuthentication", + }; + "sshd_config_files" slist => findfiles("/etc/ssh/sshd_config", "/etc/ssh/sshd_config.d/*.conf"); classes: any:: @@ -278,29 +285,14 @@ findtime = 600", classes => if_repaired("fail2ban_config_changed"), comment => "Configure fail2ban to ban IPs after 5 failed SSH attempts within 10 minutes"; - "/etc/ssh/sshd_config" - edit_line => comment_lines_matching("^PermitRootLogin\s+(?!no\s*$).*", "#"), - classes => if_repaired("sshd_hardened"), - comment => "Comment out insecure PermitRootLogin values"; - "/etc/ssh/sshd_config" - edit_line => comment_lines_matching("^PasswordAuthentication\s+(?!no\s*$).*", "#"), - classes => if_repaired("sshd_hardened"), - comment => "Comment out insecure PasswordAuthentication value"; - "/etc/ssh/sshd_config" - edit_line => comment_lines_matching("^KbdInteractiveAuthentication\s+(?!no\s*$).*", "#"), - classes => if_repaired("sshd_hardened"), - comment => "Comment out insecure KbdInteractiveAuthentication value (OpenSSH 8.7+)"; - "/etc/ssh/sshd_config" - edit_line => comment_lines_matching("^ChallengeResponseAuthentication\s+(?!no\s*$).*", "#"), + "$(sshd_config_files)" + edit_line => comment_lines_matching("^$(sshd_hardening_directives)\s+(?!no\s*$).*", "#"), classes => if_repaired("sshd_hardened"), - comment => "Comment out insecure ChallengeResponseAuthentication value (OpenSSH < 8.7)"; + comment => "Comment out insecure SSH auth directives in sshd_config and drop-ins"; "/etc/ssh/sshd_config" - edit_line => lines_present("PermitRootLogin no -PasswordAuthentication no -KbdInteractiveAuthentication no -ChallengeResponseAuthentication no"), + edit_line => prepend_if_no_line("$(sshd_hardening_directives) no"), classes => if_repaired("sshd_hardened"), - comment => "Ensure SSH hardening directives are present"; + comment => "Ensure SSH hardening directives are at the top of sshd_config, before any Include"; ubuntu_16|ubuntu_18|redhat_9|redhat_10:: "/etc/hosts" -> { "ENT-12437" } From 853c492e3e1a50e52c1ec21ad185091b06b306e6 Mon Sep 17 00:00:00 2001 From: Lars Erik Wik Date: Tue, 10 Mar 2026 13:14:04 +0100 Subject: [PATCH 2/3] Verify that the directives are actually disabled after restarting sshd Ticket: ENT-13766 Signed-off-by: Lars Erik Wik --- ci/cfengine-build-host-setup.cf | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ci/cfengine-build-host-setup.cf b/ci/cfengine-build-host-setup.cf index 25ac72227..31098e38e 100644 --- a/ci/cfengine-build-host-setup.cf +++ b/ci/cfengine-build-host-setup.cf @@ -375,10 +375,25 @@ jenkins_builds ALL=NOPASSWD: /usr/bin/podman !have_sys_user.(suse|sles|opensuse):: "useradd -u 3 sys" contain => in_shell; + linux:: + "sshd -T 2>/dev/null | grep -qiE '^PermitRootLogin no'" + depends_on => { "sshd_restarted" }, + contain => in_shell, + comment => "Verify PermitRootLogin is disabled"; + "sshd -T 2>/dev/null | grep -qiE '^PasswordAuthentication no'" + depends_on => { "sshd_restarted" }, + contain => in_shell, + comment => "Verify PasswordAuthentication is disabled"; + "sshd -T 2>/dev/null | grep -qiE '^(KbdInteractive|ChallengeResponse)Authentication no'" + depends_on => { "sshd_restarted" }, + contain => in_shell, + comment => "Verify KbdInteractiveAuthentication (OpenSSH 8.7+) or ChallengeResponseAuthentication (older) is disabled"; + services: sshd_hardened:: "sshd" service_policy => "restart", + handle => "sshd_restarted", comment => "Restart sshd to apply hardened configuration"; any:: "fail2ban" From a5e9663799f559cf3eee184f163e6f27f883e285 Mon Sep 17 00:00:00 2001 From: Lars Erik Wik Date: Tue, 10 Mar 2026 13:33:31 +0100 Subject: [PATCH 3/3] Fixed bug in policy where service restart fails On Ubuntu/Debian, the service is called ssh, not sshd. Ticket: ENT-13766 Signed-off-by: Lars Erik Wik --- ci/cfengine-build-host-setup.cf | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ci/cfengine-build-host-setup.cf b/ci/cfengine-build-host-setup.cf index 31098e38e..fbc48a644 100644 --- a/ci/cfengine-build-host-setup.cf +++ b/ci/cfengine-build-host-setup.cf @@ -189,6 +189,10 @@ bundle agent cfengine_build_host_setup "ChallengeResponseAuthentication", }; "sshd_config_files" slist => findfiles("/etc/ssh/sshd_config", "/etc/ssh/sshd_config.d/*.conf"); + debian|ubuntu:: + "sshd_service_name" string => "ssh"; + !(debian|ubuntu):: + "sshd_service_name" string => "sshd"; classes: any:: @@ -391,7 +395,7 @@ jenkins_builds ALL=NOPASSWD: /usr/bin/podman services: sshd_hardened:: - "sshd" + "$(sshd_service_name)" service_policy => "restart", handle => "sshd_restarted", comment => "Restart sshd to apply hardened configuration";