diff --git a/CHANGELOG.md b/CHANGELOG.md index 54e9300..d6a7fba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed * bkctld-update: start jail after upgrade if it was started before +* Split check into check-jails and check-setup +* bkctld-check-setup checks if the partition is mounted and writable, if firewall is configured and if all jails are started ### Deprecated diff --git a/bkctld b/bkctld index 43dc3dc..353773b 100755 --- a/bkctld +++ b/bkctld @@ -36,9 +36,13 @@ fi subcommand="${1:-}" case "${subcommand}" in - "inc" | "rm" | "check" | "stats" | "help" | "list") + "inc" | "rm" | "check-jails" | "check-setup" | "stats" | "help" | "list") "${LIBDIR}/bkctld-${subcommand}" ;; + "check") + # backward compatibility + "${LIBDIR}/bkctld-check-jails" + ;; "check-incs") option="${2:-}" if [ "${option}" = "all" ] || [ -z "${option}" ]; then diff --git a/lib/bkctld-check b/lib/bkctld-check-jails similarity index 61% rename from lib/bkctld-check rename to lib/bkctld-check-jails index 4cd5054..80981f5 100755 --- a/lib/bkctld-check +++ b/lib/bkctld-check-jails @@ -14,43 +14,6 @@ nb_ok=0 nb_unkn=0 output="" -# Check if the backup disk is properly mounted - -if [ -b "${BACKUP_DISK}" ]; then - # If backup disk is encrypted, verify that it's open - cryptsetup isLuks "${BACKUP_DISK}" - if [ "$?" -eq 0 ]; then - if [ ! -b '/dev/mapper/backup' ]; then - echo "Luks disk \`${BACKUP_DISK}' is not mounted !\n" - echo "cryptsetup luksOpen ${BACKUP_DISK} backup" - exit 2 - fi - # Change value to real device - BACKUP_DISK='/dev/mapper/backup' - fi - # Verify that it's mounted and writable - findmnt --source ${BACKUP_DISK} -O rw > /dev/null - if [ "$?" -ne 0 ]; then - echo "Backup disk \`${BACKUP_DISK}' is not mounted (or read-only) !\n" - echo "mount ${BACKUP_DISK} /backup" - exit 2 - fi -fi - -# Check if the firewall file is sourced - -minifirewall_config=/etc/default/minifirewall - -if [ -n "${FIREWALL_RULES}" ] \ -&& [ -r "${FIREWALL_RULES}" ] \ -&& [ -f "${minifirewall_config}" ]; then - if ! grep -qE "^(\.|source) ${FIREWALL_RULES}" "${minifirewall_config}"; then - nb_warn=$((nb_warn + 1)) - output="${output}WARNING - Firewall file '${FIREWALL_RULES}' doesn't seem to be sourced by '${minifirewall_config}'\n" - [ "${return}" -le 1 ] && return=1 - fi -fi - # Check each jail status check_jail() { @@ -64,8 +27,8 @@ check_jail() { check_policy_file=$(current_jail_check_policy_file "${jail_name}") if [ -f "${check_policy_file}" ]; then - local_critical=$(read_variable "${check_policy_file}" "CRITICAL") - local_warning=$(read_variable "${check_policy_file}" "WARNING") + local_critical=$(read_numerical_variable "${check_policy_file}" "CRITICAL") + local_warning=$(read_numerical_variable "${check_policy_file}" "WARNING") else unset local_critical unset local_warning diff --git a/lib/bkctld-check-setup b/lib/bkctld-check-setup new file mode 100755 index 0000000..e68648d --- /dev/null +++ b/lib/bkctld-check-setup @@ -0,0 +1,86 @@ +#!/bin/sh +# +# Run check on jails (NRPE output) +# Usage: check +# + +# shellcheck source=./includes +LIBDIR="$(dirname $0)" && . "${LIBDIR}/includes" + +return=0 +nb_crit=0 +nb_warn=0 +nb_ok=0 +nb_unkn=0 +output="" + +# Verify backup partition is mounted and writable + +findmnt --mountpoint "${BACKUP_PARTITION}" -O rw > /dev/null +if [ "$?" -ne 0 ]; then + nb_crit=$((nb_crit + 1)) + output="${output}CRITICAL - Backup disk \`/backup' is not mounted (or read-only) !\n" + return=2 +else + nb_ok=$((nb_ok + 1)) + output="${output}OK - Backup disk \`/backup' is mounted and writable.\n" +fi + +# Check if the firewall file is sourced + +minifirewall_config=/etc/default/minifirewall + +if [ -n "${FIREWALL_RULES}" ] \ +&& [ -r "${FIREWALL_RULES}" ] \ +&& [ -f "${minifirewall_config}" ]; then + if grep -qE "^(\.|source) ${FIREWALL_RULES}" "${minifirewall_config}"; then + nb_ok=$((nb_ok + 1)) + output="${output}OK - Firewall file \`${FIREWALL_RULES}' is sourced by \`${minifirewall_config}'.\n" + else + nb_warn=$((nb_warn + 1)) + output="${output}WARNING - Firewall file \`${FIREWALL_RULES}' doesn't seem to be sourced by \`${minifirewall_config}'\n" + [ "${return}" -le 1 ] && return=1 + fi +fi + +# Check if jails are started +set -x +nb_on=0 +nb_off=0 +for jail_name in $(jails_list); do + if "${LIBDIR}/bkctld-is-on" "${jail_name}"; then + nb_on=$((nb_on + 1)) + else + expected_state="ON" + check_policy_file=$(current_jail_check_policy_file "${jail_name}") + + if [ -f "${check_policy_file}" ]; then + expected_state=$(read_variable "${check_policy_file}" "EXPECTED_STATE") + fi + if [ "${expected_state}" != "OFF" ]; then + nb_off=$((nb_off + 1)) + fi + fi +done +if [ "${nb_off}" -eq 0 ]; then + output="${output}OK - all jails are in their expected state .\n" +else + output="${output}CRITICAL - ${nb_off} jail(s) shouldn't be OFF !\n" + nb_crit=$((nb_crit + 1)) + [ "${return}" -le 2 ] && return=2 +fi +set +x + +[ "${return}" -ge 0 ] && header="OK" +[ "${return}" -ge 1 ] && header="WARNING" +[ "${return}" -ge 2 ] && header="CRITICAL" +[ "${return}" -ge 3 ] && header="UNKNOWN" + +printf "%s - %s UNK / %s CRIT / %s WARN / %s OK\n\n" "${header}" "${nb_unkn}" "${nb_crit}" "${nb_warn}" "${nb_ok}" + +printf "${output}" | grep -E "^UNKNOWN" +printf "${output}" | grep -E "^CRITICAL" +printf "${output}" | grep -E "^WARNING" +printf "${output}" | grep -E "^OK" + +exit "${return}" diff --git a/lib/includes b/lib/includes index 6ba6fec..4ca709e 100755 --- a/lib/includes +++ b/lib/includes @@ -7,12 +7,13 @@ LIBDIR=${LIBDIR:-/usr/lib/bkctld} CONFDIR="${CONFDIR:-/etc/evobackup}" BACKUP_DISK="${BACKUP_DISK:-}" -JAILDIR="${JAILDIR:-/backup/jails}" -INCDIR="${INCDIR:-/backup/incs}" +BACKUP_PARTITION="${BACKUP_PARTITION:-/backup}" +JAILDIR="${JAILDIR:-${BACKUP_PARTITION}/jails}" +INCDIR="${INCDIR:-${BACKUP_PARTITION}/incs}" TPLDIR="${TPLDIR:-/usr/share/bkctld}" LOCALTPLDIR="${LOCALTPLDIR:-/usr/local/share/bkctld}" LOCKDIR="${LOCKDIR:-/run/lock/bkctld}" -INDEX_DIR="${INDEX_DIR:-/backup/index}" +INDEX_DIR="${INDEX_DIR:-${BACKUP_PARTITION}/index}" IDX_FILE="${IDX_FILE:-${INDEX_DIR}/bkctld-jails.idx}" SSHD_PID="${SSHD_PID:-/run/sshd.pid}" SSHD_CONFIG="${SSHD_CONFIG:-/etc/ssh/sshd_config}" @@ -337,6 +338,15 @@ read_variable() { file=${1:?} var_name=${2:?} + pattern="^\s*${var_name}=.+" + + grep --extended-regexp --only-matching "${pattern}" "${file}" | cut -d= -f2 +} + +read_numerical_variable() { + file=${1:?} + var_name=${2:?} + pattern="^\s*${var_name}=-?[0-9]+" grep --extended-regexp --only-matching "${pattern}" "${file}" | cut -d= -f2 diff --git a/test/checks.bats b/test/checks.bats index 77a7b4a..f8e5c85 100644 --- a/test/checks.bats +++ b/test/checks.bats @@ -3,33 +3,38 @@ load test_helper -@test "Check OK for default values" { - touch "${JAILPATH}/var/log/lastlog" - # With default values (2 days critical, 1 day warning), - # a freshly connected jail should be "ok" - run /usr/lib/bkctld/bkctld-check +@test "Check jails OK" { + run /usr/lib/bkctld/bkctld-check-jails assert_equal "0" "$status" } -@test "Check WARNING for default values" { +@test "Check jails OK for default values" { + touch "${JAILPATH}/var/log/lastlog" + # With default values (2 days critical, 1 day warning), + # a freshly connected jail should be "ok" + run /usr/lib/bkctld/bkctld-check-jails + assert_equal "0" "$status" +} + +@test "Check jails WARNING for default values" { lastlog_date=$(date -d -2days --iso-8601=seconds) touch --date="${lastlog_date}" "${JAILPATH}/var/log/lastlog" # With default values (2 days critical, 1 day warning), # a 2 days old jail should be "warning" - run /usr/lib/bkctld/bkctld-check + run /usr/lib/bkctld/bkctld-check-jails assert_equal "1" "$status" } -@test "Check CRITICAL for default values" { +@test "Check jails CRITICAL for default values" { lastlog_date=$(date -d -3days --iso-8601=seconds) touch --date="${lastlog_date}" "${JAILPATH}/var/log/lastlog" # With default values (2 days critical, 1 day warning), # a 3 days old jail should be "critical" - run /usr/lib/bkctld/bkctld-check + run /usr/lib/bkctld/bkctld-check-jails assert_equal "2" "$status" } -@test "Check OK for custom values" { +@test "Check jails OK for custom values" { lastlog_date=$(date -d -3days --iso-8601=seconds) touch --date="${lastlog_date}" "${JAILPATH}/var/log/lastlog" @@ -39,11 +44,11 @@ WARNING=96 OUT # With custom values (5 days critical, 4 days warning), # a 3 days old jail should be "ok" - run /usr/lib/bkctld/bkctld-check + run /usr/lib/bkctld/bkctld-check-jails assert_equal "0" "$status" } -@test "Check WARNING for custom values" { +@test "Check jails WARNING for custom values" { lastlog_date=$(date -d -3days --iso-8601=seconds) touch --date="${lastlog_date}" "${JAILPATH}/var/log/lastlog" @@ -53,11 +58,11 @@ WARNING=48 OUT # With custom values (4 days critical, 3 days warning), # a 3 days old jail should be "warning" - run /usr/lib/bkctld/bkctld-check + run /usr/lib/bkctld/bkctld-check-jails assert_equal "1" "$status" } -@test "Check CRITICAL for custom values" { +@test "Check jails CRITICAL for custom values" { lastlog_date=$(date -d -10days --iso-8601=seconds) touch --date="${lastlog_date}" "${JAILPATH}/var/log/lastlog" @@ -67,11 +72,11 @@ WARNING=48 OUT # With custom values (4 days critical, 3 days warning), # a 10 days old jail should be "critical" - run /usr/lib/bkctld/bkctld-check + run /usr/lib/bkctld/bkctld-check-jails assert_equal "2" "$status" } -@test "Check OK for disabled WARNING" { +@test "Check jails OK for disabled WARNING" { lastlog_date=$(date -d -2days --iso-8601=seconds) touch --date="${lastlog_date}" "${JAILPATH}/var/log/lastlog" @@ -80,11 +85,11 @@ WARNING=0 OUT # With custom values (warning disabled, default critical), # a 2 days old jail should still be "ok" - run /usr/lib/bkctld/bkctld-check + run /usr/lib/bkctld/bkctld-check-jails assert_equal "0" "$status" } -@test "Check WARNING for disabled CRITICAL" { +@test "Check jails WARNING for disabled CRITICAL" { lastlog_date=$(date -d -3days --iso-8601=seconds) touch --date="${lastlog_date}" "${JAILPATH}/var/log/lastlog" @@ -93,11 +98,11 @@ CRITICAL=0 OUT # With custom values (critical disabled, default warning), # a 3 days old jail should only be "warning" - run /usr/lib/bkctld/bkctld-check + run /usr/lib/bkctld/bkctld-check-jails assert_equal "1" "$status" } -@test "Custom values are parsed with only integers after equal" { +@test "Custom jails values are parsed with only integers after equal" { lastlog_date=$(date -d -3days --iso-8601=seconds) touch --date="${lastlog_date}" "${JAILPATH}/var/log/lastlog" @@ -106,7 +111,7 @@ CRITICAL=0 # foo OUT # With custom values (critical disabled, default warning), # a 3 days old jail should only be "warning" - run /usr/lib/bkctld/bkctld-check + run /usr/lib/bkctld/bkctld-check-jails assert_equal "1" "$status" } @@ -119,7 +124,7 @@ OUT OUT # With commented custom values (critical disabled), # a 3 days old jail should still be "critical" - run /usr/lib/bkctld/bkctld-check + run /usr/lib/bkctld/bkctld-check-jails assert_equal "2" "$status" } @@ -132,40 +137,85 @@ CRITICAL=foo OUT # With commented custom values (critical disabled), # a 3 days old jail should still be "critical" - run /usr/lib/bkctld/bkctld-check + run /usr/lib/bkctld/bkctld-check-jails assert_equal "2" "$status" } -@test "Check WARNING if firewall rules are not sourced" { +@test "Check setup WARNING if firewall rules are not sourced" { + /usr/lib/bkctld/bkctld-start ${JAILNAME} + firewall_rules_file="/etc/firewall.rc.jails" set_variable "/etc/default/bkctld" "FIREWALL_RULES" "${firewall_rules_file}" echo "" > "${firewall_rules_file}" # Without sourcing echo "" > "/etc/default/minifirewall" - # … the check should be "critical" - run /usr/lib/bkctld/bkctld-check + # … the check should be "warning" + run /usr/lib/bkctld/bkctld-check-setup assert_equal "1" "$status" } -@test "Check OK if firewall rules are sourced" { +@test "Check setup OK if firewall rules are sourced" { + /usr/lib/bkctld/bkctld-start ${JAILNAME} + firewall_rules_file="/etc/firewall.rc.jails" set_variable "/etc/default/bkctld" "FIREWALL_RULES" "${firewall_rules_file}" echo "" > "${firewall_rules_file}" # Sourcing file with '.' echo ". ${firewall_rules_file}" > "/etc/default/minifirewall" - # … the check should be "critical" - run /usr/lib/bkctld/bkctld-check + # … the check should be "ok" + run /usr/lib/bkctld/bkctld-check-setup assert_equal "0" "$status" # Sourcing file with 'source' echo "source ${firewall_rules_file}" > "/etc/default/minifirewall" - # … the check should be "critical" - run /usr/lib/bkctld/bkctld-check + # … the check should be "ok" + run /usr/lib/bkctld/bkctld-check-setup assert_equal "0" "$status" } +@test "Check setup CRITICAL if jail is stopped" { + run /usr/lib/bkctld/bkctld-check-setup + assert_equal "2" "$status" +} + +@test "Check setup OK if all jails are started" { + /usr/lib/bkctld/bkctld-start ${JAILNAME} + + run /usr/lib/bkctld/bkctld-check-setup + assert_equal "0" "$status" +} + +@test "Check setup OK if jail is supposed to be stopped" { + cat > "/etc/evobackup/${JAILNAME}.d/check_policy" <