From a9d2e76cdbdafc75270fb2ff1080ff6336560662 Mon Sep 17 00:00:00 2001 From: damcav35 <51324122+damcav35@users.noreply.github.com> Date: Wed, 6 Aug 2025 11:13:49 +0200 Subject: [PATCH] Damcava35/update lib (#277) * update lib/utils.sh - add 'is_pkg_a_dependency', to ensure a package is not needed by some others before removing it -> will be used in debian 12 CIS by at least the 2.1.5 recommendation - update 'is_service_enabled' to use 'systemd' instead of 'rc.d', as we are now only supporting debian LTS using systemd - add 'is_using_sbin_init' to ensure we can use systemctl, in case of running on non detected container - add 'manage_service' to enable / disable service using systemctl * chore: update script related to systemctl / service - configure_systemd-timesync.sh: use "is_service_enabled" instead of calling systemctl - disable_automounting.sh: use "manage_service" instead of "update-rc.d" - enable_auditd.sh: use "manage_service" instead of "update-rc.d" - enable_cron.sh: use "manage_service" instead of "update-rc.d" - enable_syslog-ng.sh: use "manage_service" instead of "update-rc.d" --------- Co-authored-by: Damien Cavagnini --- bin/hardening/configure_systemd-timesyncd.sh | 4 +- bin/hardening/disable_automounting.sh | 2 +- bin/hardening/enable_auditd.sh | 3 +- bin/hardening/enable_cron.sh | 3 +- bin/hardening/enable_syslog-ng.sh | 3 +- lib/utils.sh | 65 +++++++++++++++++++- tests/hardening/enable_auditd.sh | 11 ++-- 7 files changed, 77 insertions(+), 14 deletions(-) diff --git a/bin/hardening/configure_systemd-timesyncd.sh b/bin/hardening/configure_systemd-timesyncd.sh index 9a71aca..af63d12 100755 --- a/bin/hardening/configure_systemd-timesyncd.sh +++ b/bin/hardening/configure_systemd-timesyncd.sh @@ -21,8 +21,8 @@ SERVICE_NAME="systemd-timesyncd" # This function will be called if the script status is on enabled / audit mode audit() { - status=$(systemctl is-enabled "$SERVICE_NAME") - if [ "$status" = "enabled" ]; then + is_service_enabled "$SERVICE_NAME" + if [ "$FNRET" -eq 0 ]; then ok "$SERVICE_NAME is enabled" else crit "$SERVICE_NAME is disabled" diff --git a/bin/hardening/disable_automounting.sh b/bin/hardening/disable_automounting.sh index 20082bc..66918ee 100755 --- a/bin/hardening/disable_automounting.sh +++ b/bin/hardening/disable_automounting.sh @@ -36,7 +36,7 @@ apply() { is_service_enabled "$SERVICE_NAME" if [ "$FNRET" = 0 ]; then info "Disabling $SERVICE_NAME" - update-rc.d "$SERVICE_NAME" remove >/dev/null 2>&1 + manage_service disable "$SERVICE_NAME" else ok "$SERVICE_NAME is disabled" fi diff --git a/bin/hardening/enable_auditd.sh b/bin/hardening/enable_auditd.sh index 2f9df99..51c1d12 100755 --- a/bin/hardening/enable_auditd.sh +++ b/bin/hardening/enable_auditd.sh @@ -50,8 +50,7 @@ apply() { ok "$SERVICE_NAME is enabled" else warn "$SERVICE_NAME is not enabled, enabling it" - update-rc.d "$SERVICE_NAME" remove >/dev/null 2>&1 - update-rc.d "$SERVICE_NAME" defaults >/dev/null 2>&1 + manage_service enable "$SERVICE_NAME" fi } diff --git a/bin/hardening/enable_cron.sh b/bin/hardening/enable_cron.sh index 37d1c97..a417c3b 100755 --- a/bin/hardening/enable_cron.sh +++ b/bin/hardening/enable_cron.sh @@ -47,8 +47,7 @@ apply() { is_service_enabled "$SERVICE_NAME" if [ "$FNRET" != 0 ]; then info "Enabling $SERVICE_NAME" - update-rc.d "$SERVICE_NAME" remove >/dev/null 2>&1 - update-rc.d "$SERVICE_NAME" defaults >/dev/null 2>&1 + manage_service enable "$SERVICE_NAME" else ok "$SERVICE_NAME is enabled" fi diff --git a/bin/hardening/enable_syslog-ng.sh b/bin/hardening/enable_syslog-ng.sh index 3800458..71feeb8 100755 --- a/bin/hardening/enable_syslog-ng.sh +++ b/bin/hardening/enable_syslog-ng.sh @@ -46,8 +46,7 @@ apply() { is_service_enabled "$SERVICE_NAME" if [ "$FNRET" != 0 ]; then info "Enabling $SERVICE_NAME" - update-rc.d "$SERVICE_NAME" remove >/dev/null 2>&1 - update-rc.d "$SERVICE_NAME" defaults >/dev/null 2>&1 + manage_service enable "$SERVICE_NAME" >/dev/null 2>&1 else ok "$SERVICE_NAME is enabled" fi diff --git a/lib/utils.sh b/lib/utils.sh index 84388d2..a540cb5 100644 --- a/lib/utils.sh +++ b/lib/utils.sh @@ -316,7 +316,17 @@ does_group_exist() { is_service_enabled() { local SERVICE=$1 - if [ "$($SUDO_CMD find /etc/rc?.d/ -name "S*$SERVICE" -print | wc -l)" -gt 0 ]; then + + # if running in a container, it does not make much sense to test for systemd / service + # the var "IS_CONTAINER" defined in lib/constant may not be enough, in case we are using systemd slices + # currently, did not find a unified way to manage all cases, so we check this only for systemctl usage + is_using_sbin_init + if [ "$FNRET" -eq 1 ]; then + debug "host was not started using '/sbin/init', systemd should not be available" + FNRET=1 + return + fi + if $SUDO_CMD systemctl -t service is-enabled "$SERVICE" >/dev/null; then debug "Service $SERVICE is enabled" FNRET=0 else @@ -589,6 +599,36 @@ is_pkg_installed() { fi } +is_pkg_a_dependency() { + # check if a package is needed by another installed package + # This is used to avoid removing a legit package while trying to remove an unwanted one + local PKG_NAME=$1 + # ex: 'dnsmasq' is going to install 'dnsmasq-base' + # We don't care about 'dnsmasq-base' here, we want to know about the others packages needing 'dnsmasq' + # so we put 'dnsmasq-base' as a 'known_deps' + shift + local known_deps="$*" + + PKG_DEPENDENCIES="" + # shellcheck disable=2162 + while read pkg_dep_name; do + is_pkg_installed "$pkg_dep_name" + if [ "$FNRET" -eq 0 ] && ! grep -w "$pkg_dep_name" <<<"$known_deps" >/dev/null; then + PKG_DEPENDENCIES="$PKG_DEPENDENCIES $pkg_dep_name" + fi + + done <<<"$(apt-cache rdepends "$PKG_NAME" | sed -e '1,2d' -e 's/^\ *//g' -e 's/^|//g' | sort -u)" + + if [ -n "$PKG_DEPENDENCIES" ]; then + debug "$PKG_NAME is a dependency for some packages: $PKG_DEPENDENCIES" + FNRET=0 + else + debug "$PKG_NAME is not a dependency for another installed package" + FNRET=1 + fi + +} + # Returns Debian major version get_debian_major_version() { @@ -621,3 +661,26 @@ get_distribution() { is_running_in_container() { awk -F/ '$2 == "'"$1"'"' /proc/self/cgroup } + +is_using_sbin_init() { + FNRET=0 + # remove '\0' to avoid 'command substitution: ignored null byte in input' + if [[ $($SUDO_CMD cat /proc/1/cmdline | tr -d '\0') != "/sbin/init" ]]; then + debug "init process is not '/sbin/init'" + FNRET=1 + fi +} + +manage_service() { + local action="$1" + local service="$2" + + is_using_sbin_init + if [ "$FNRET" -ne 0 ]; then + debug "/sbin/init not used, systemctl wont manage service $service" + return + fi + + systemctl "$action" "$service" >/dev/null 2>&1 + +} diff --git a/tests/hardening/enable_auditd.sh b/tests/hardening/enable_auditd.sh index 421b1ce..32f0822 100644 --- a/tests/hardening/enable_auditd.sh +++ b/tests/hardening/enable_auditd.sh @@ -1,9 +1,11 @@ # shellcheck shell=bash # run-shellcheck test_audit() { + describe Prepare failing test + apt remove -y auditd + describe Running on blank host - register_test retvalshouldbe 0 - dismiss_count_for_test + register_test retvalshouldbe 1 # shellcheck disable=2154 run blank "${CIS_CHECKS_DIR}/${script}.sh" --audit-all @@ -12,7 +14,8 @@ test_audit() { "${CIS_CHECKS_DIR}/${script}.sh" || true describe Checking resolved state - register_test retvalshouldbe 0 - register_test contain "[ OK ] auditd is enabled" + # service still wont be enabled due to tests running inside a docker container + register_test retvalshouldbe 1 + register_test contain "[ OK ] auditd is installed" run resolved "${CIS_CHECKS_DIR}/${script}.sh" --audit-all }