Checks improved

This commit is contained in:
Martin Berghaus
2026-05-09 21:59:40 +02:00
parent ee114ee732
commit 00b920763e
30 changed files with 21 additions and 20 deletions
@@ -1,7 +0,0 @@
#!/bin/bash
_CURRENT_APP='docker compose version'
${_CURRENT_APP} > /dev/null 2>&1 \
&& exit 0
exit 1
@@ -1,5 +0,0 @@
#!/bin/bash
docker --version > /dev/null 2>&1 \
&& exit 0
exit 1
@@ -1,5 +0,0 @@
#!/bin/bash
nginx -v > /dev/null 2>&1 \
&& exit 0
exit 1
@@ -1,16 +0,0 @@
#!/bin/bash
# Fail because of unnecessary custom config
grep "Wants=network-online.target" /lib/systemd/system/nginx.service > /dev/null 2>&1 \
&& [ -f "/etc/systemd/system/nginx.service" ] \
&& exit 1
# Success if system config is ok
grep "Wants=network-online.target" /lib/systemd/system/nginx.service > /dev/null 2>&1 \
&& exit 0
# Success if custom config fixes system config
grep "Wants=network-online.target" /etc/systemd/system/nginx.service > /dev/null 2>&1 \
&& exit 0
exit 1
@@ -1,9 +0,0 @@
#!/bin/bash
[ "$(id -u)" != "0" ] \
&& printf "(INSUFFICENT RIGHTS) " \
&& exit 1
crontab -l | grep -E "[0-9]{1,2}[ \*]{8}[[:blank:]]*\/cis\/setupCoreOntoThisHost.sh" > /dev/null 2>&1 \
&& exit 0
exit 1
@@ -1,5 +0,0 @@
#!/bin/bash
git --version > /dev/null 2>&1 \
&& exit 0
exit 1
@@ -1,10 +0,0 @@
#!/bin/bash
_CURRENT_FILE='/etc/hostname'
#The file must be readable, then
#the number of lines containing a '.' must be zero.
[ -r "${_CURRENT_FILE}" ] \
&& [ "$(grep -cF '.' "${_CURRENT_FILE}")" -gt 0 ] \
&& exit 0
exit 1
@@ -1,8 +0,0 @@
#!/bin/bash
_PKG_NAME='libpam-google-authenticator'
dpkg -l | grep -q -F "${_PKG_NAME}" 2> /dev/null \
&& exit 0
exit 1
@@ -1,8 +0,0 @@
#!/bin/bash
_PKG_NAME='libpam-pwquality'
dpkg -l | grep -q -F "${_PKG_NAME}" 2> /dev/null \
&& exit 0
exit 1
@@ -1,5 +0,0 @@
#!/bin/bash
ssh -V > /dev/null 2>&1 \
&& exit 0
exit 1
@@ -1,15 +0,0 @@
#!/bin/bash
_CURRENT_FILE='/home/jenkins/.ssh/authorized_keys'
[ "$(id -u)" != "0" ] \
&& printf "(INSUFFICENT RIGHTS) " \
&& exit 1
#File has to be readable, then
#search for '/definitions/' in the path of current file, after readlink expanded a potential symlink.
[ -r "${_CURRENT_FILE}" ] \
&& readlink -f "${_CURRENT_FILE}" | grep -q "/definitions/" \
&& exit 0
exit 1
@@ -1,25 +0,0 @@
#!/bin/bash
_CURRENT_FILE='/root/.ssh/authorized_keys'
[ "$(id -u)" != "0" ] \
&& printf "(INSUFFICENT RIGHTS) " \
&& exit 1
#No file is ok
[ ! -e "${_CURRENT_FILE}" ] \
&& exit 0
#The file must be readable, then
#all comments and all blank lines are removed, after which the number of remaining lines must be zero.
[ -r "${_CURRENT_FILE}" ] \
&& [ "0" == "$(cat "${_CURRENT_FILE}" | sed 's/[[:blank:]]*#.*//' | sed '/^$/d' | grep -c .)" ] \
&& exit 0
#File has to be readable, then
#search for '/definitions/' in the path of current file, after readlink expanded a potential symlink.
[ -r "${_CURRENT_FILE}" ] \
&& readlink -f "${_CURRENT_FILE}" | grep -q "/definitions/" \
&& exit 0
exit 1
@@ -1,21 +0,0 @@
#!/bin/bash
_CURRENT_FILE='/etc/ssh/sshd_config.d/AccessRestriction.conf'
#No file is NOT ok
[ ! -e "${_CURRENT_FILE}" ] \
&& exit 1
#File has to be readable, then
#search for '/definitions/' in the path of current file, after readlink expanded a potential symlink.
[ -r "${_CURRENT_FILE}" ] \
&& readlink -f "${_CURRENT_FILE}" | grep -q "/definitions/" \
&& exit 0
#File has to be readable, then
#search for '/core/default/' in the path of current file, after readlink expanded a potential symlink.
[ -r "${_CURRENT_FILE}" ] \
&& readlink -f "${_CURRENT_FILE}" | grep -q "/core/default/" \
&& exit 0
exit 1
@@ -1,5 +0,0 @@
#!/bin/bash
getent group ssh_login > /dev/null \
&& exit 0
exit 1
@@ -1,13 +0,0 @@
#!/bin/bash
_CURRENT_FILE='/root/.ssh/id_ed25519'
[ "$(id -u)" != "0" ] \
&& printf "(INSUFFICENT RIGHTS) " \
&& exit 1
#File has to be readable and no passphrase should be needed.
ssh-keygen -y -P "" -f "${_CURRENT_FILE}" &> /dev/null \
&& exit 0
exit 1
@@ -1,5 +0,0 @@
#!/bin/bash
getent group ssh_login | grep -q jenkins \
&& exit 0
exit 1
@@ -1,21 +0,0 @@
#!/bin/bash
_CURRENT_FILE='/etc/sudoers.d/allow-jenkins-updateRepositories'
[ "$(id -u)" != "0" ] \
&& printf "(INSUFFICENT RIGHTS) " \
&& exit 1
#File has to be readable, then
#search for '/definitions/' in the path of current file, after readlink expanded a potential symlink.
[ -r "${_CURRENT_FILE}" ] \
&& readlink -f "${_CURRENT_FILE}" | grep -q "/definitions/" \
&& exit 0
#File has to be readable, then
#search for '/core/default/' in the path of current file, after readlink expanded a potential symlink.
[ -r "${_CURRENT_FILE}" ] \
&& readlink -f "${_CURRENT_FILE}" | grep -q "/core/default/" \
&& exit 0
exit 1
@@ -1,12 +0,0 @@
#!/bin/bash
_CURRENT_USER='jenkins'
[ "$(id -u)" != "0" ] \
&& printf "(INSUFFICENT RIGHTS) " \
&& exit 1
id -u "${_CURRENT_USER}" > /dev/null 2>&1 \
&& exit 0
exit 1
@@ -1,11 +0,0 @@
#!/bin/bash
_FILE_NAME='/etc/adduser.conf'
# The first expression should filter the line conaining the key.
# - here a regular expression (-E) is used to enforce the line starts with the key.
# Second expression looks for the uninterpreted fix string (-F), but without output.
grep -E '^NAME_REGEX=.*$' "${_FILE_NAME}" | grep -q -F '^[a-z][-a-z0-9_.]*\$?$' 2> /dev/null \
&& exit 0
exit 1
@@ -1,6 +0,0 @@
#/bin/bash
[ "$(apt-get -s -o Debug::NoLocking=true upgrade | grep -c -E '^Inst')" = "0" ] \
&& exit 0
exit 1
@@ -1,12 +0,0 @@
#!/bin/bash
_CURRENT_FILE='/etc/localtime'
#The file must be readable, then
#the number of lines containing "CET" must be greater than zero, and
#the number of lines containing "CEST" must also be greater than zero.
[ -r "${_CURRENT_FILE}" ] \
&& [ "$(zdump -v "${_CURRENT_FILE}" | head -n 10 | grep 'CET' | grep -c .)" -gt "0" ] \
&& [ "$(zdump -v "${_CURRENT_FILE}" | head -n 10 | grep 'CEST' | grep -c .)" -gt "0" ] \
&& exit 0
exit 1
@@ -1,10 +0,0 @@
#!/bin/bash
_CURRENT_FILE='/etc/timezone'
#The file must be readable, then
#the number of lines containing "Europe/Berlin" must be one.
[ -r "${_CURRENT_FILE}" ] \
&& [ "1" == "$(cat "${_CURRENT_FILE}" | grep 'Europe/Berlin' | grep -c .)" ] \
&& exit 0
exit 1
@@ -1,14 +0,0 @@
#!/bin/bash
#
# There are three components working together:
# - systemctl status unattended-upgrades.service (One-Shot-Service, loaded means system knows the service, it DOES NOT run in background)
# - systemctl status apt-daily.timer (apt update)
# - systemctl status apt-daily-upgrade.timer (apt upgrade)
#
# So disable/enaable the Upgrade with:
# - systemctl disable --now apt-daily-upgrade.timer (--now means disable and stop)
# - systemctl enable --now apt-daily-upgrade.timer (--now means enable and start)
#
! systemctl is-enabled apt-daily-upgrade.timer > /dev/null 2>&1 \
&& exit 0
exit 1
@@ -1,5 +0,0 @@
#!/bin/bash
zfs --version > /dev/null 2>&1 \
&& exit 0
exit 1
@@ -1,13 +0,0 @@
#!/bin/bash
_CURRENT_POOL='zpool1'
#Check if the tool 'zfs' is available, then
#retrieve the property 'atime' from 'zpool1', without header and compare the result with 'off'
#because this the feature 'atime' logs each access, there are many avoidable writes.
#Set with: 'zfs set atime=off zpool1'
zfs version &> /dev/null \
&& [ "$(zfs get atime -Ho value ${_CURRENT_POOL} 2> /dev/null)" == "off" ] \
&& exit 0
exit 1
@@ -1,12 +0,0 @@
#!/bin/bash
_CURRENT_POOL='zpool1'
#Check if the tool 'zfs' is available, then
#retrieve the property 'compression' from 'zpool1', without header and compare the result with 'lz4'
#Set with: 'zfs set compression=lz4 zpool1'
zfs version &> /dev/null \
&& [ "$(zfs get compression -Ho value ${_CURRENT_POOL} 2> /dev/null)" == "lz4" ] \
&& exit 0
exit 1
@@ -1,12 +0,0 @@
#!/bin/bash
_CURRENT_ZFS='zpool1'
#Check if the tool 'zfs' is available, then
#retrieve the property 'mountpoint' from 'zpool1', without header and compare the result with '/zpool1'
#Set with: 'zfs set mountpount=default'
zfs version &> /dev/null \
&& [ "$(zfs get mountpoint -Ho value ${_CURRENT_ZFS} 2> /dev/null)" == "/${_CURRENT_ZFS}" ] \
&& exit 0
exit 1
@@ -1,10 +0,0 @@
#!/bin/bash
_CURRENT_POOL='zpool1'
#Check if the tool 'zpool' is available, then
#retrieve the property 'ashift' from 'zpool1', without header and compare the result with '12'
zpool version &> /dev/null \
&& [ "$(zpool get ashift -Ho value ${_CURRENT_POOL} 2> /dev/null)" == "12" ] \
&& exit 0
exit 1
+18 -20
View File
@@ -1,12 +1,5 @@
#!/bin/bash
_SCRIPT="$(readlink -f "${0}" 2> /dev/null)"
# Folders always ends with an tailing '/'
_CIS_ROOT="${_SCRIPT%%/script/check/*}/" #Removes longest matching pattern '/script/check/*' from the end
_SCRIPT_PATH="${_CIS_ROOT:?"Missing CIS_ROOT"}script/"
_OWN_DOMAIN="$(${_CIS_ROOT}core/printOwnDomain.sh)"
_OWN_DEFINITIONS="${_CIS_ROOT}definitions/${_OWN_DOMAIN:?"Missing OWN_DOMAIN"}/"
source /cis/core/base.module.sh
@@ -20,7 +13,7 @@ function run_as_root() {
}
function scripts_are_updateable_by_git() {
git -C "${_SCRIPT_PATH:?"Missing SCRIPT_PATH"}" pull > /dev/null 2>&1 \
git -C "${CIS[SCRIPTDIR]?"Missing CIS_SCRIPTDIR"}" pull > /dev/null 2>&1 \
&& echo OK \
&& return 0
@@ -29,31 +22,36 @@ function scripts_are_updateable_by_git() {
}
function allChecks() {
local _CHECK_PATH _MODE_PATH
local _CHECK_PATH _MODE_PATH _CHECK_FILES
_CHECK_PATH="${1:?"allChecks(): Missing first parameter CHECK_PATH"}check/"
_MODE_PATH="${2:-all}/"
readonly _CHECK_PATH _MODE_PATH
_CHECK_FILES="${_CHECK_PATH}${_MODE_PATH}"
readonly _CHECK_PATH _MODE_PATH _CHECK_FILES
echo " - ${_CHECK_PATH}host/${_MODE_PATH}*.check.sh"
[ "$(ls -1 ${_CHECK_PATH}host/${_MODE_PATH}*.check.sh 2> /dev/null | grep -cE '.*')" == "0" ] \
&& echo " nothing to do" \
&& return 0
for _CURRENT_CHECK in ${_CHECK_PATH}host/${_MODE_PATH}*.check.sh; do
local _CHECK_FOUND="false"
echo " - ${_CHECK_FILES}*.check.sh"
for _CURRENT_CHECK in "${_CHECK_FILES}"*.check.sh; do
! [ -x "${_CURRENT_CHECK}" ] \
&& continue
_CHECK_FOUND="true"
_NAME="$(basename ${_CURRENT_CHECK} | cut -d'.' -f1)"
_CONTEXT="$(echo ${_NAME} | cut -d'_' -f1)"
_CHECK="$(echo ${_NAME} | cut -d'_' -f2- | tr '_' ' ')"
_RESULT="$("${_CURRENT_CHECK}" && echo OK || echo FAIL)"
echo " ${_CONTEXT^^} ${_CHECK}: ${_RESULT}"
done
[ "${_CHECK_FOUND}" == "false" ] \
&& echo " nothing to do" \
&& return 0
}
echo "PRECONDITION run as root: $(run_as_root)"
echo "PRECONDITION scripts are updateable by git: $(scripts_are_updateable_by_git)"
echo
echo "Check all (common):"
allChecks "${_SCRIPT_PATH}"
allChecks "${CIS[DEFAULTDEFINITIONS]?"Missing CIS_DEFAULTDEFINITIONS"}"
echo "Check all (own):"
allChecks "${_OWN_DEFINITIONS}"
allChecks "${CIS[DOMAINDEFINITIONS]?"Missing CIS_DOMAINDEFINITIONS"}"
echo "Check this host:"
allChecks "${_OWN_DEFINITIONS}" "$(hostname -s)"
allChecks "${CIS[DOMAINDEFINITIONS]}" "$(hostname -s)"