Many improvements and bump to version 22.03. See CHANGELOG

This commit is contained in:
Jérémy Dubois 2022-03-10 16:46:31 +01:00
parent 11d77659a0
commit 3fcab1eeb3
2 changed files with 288 additions and 134 deletions

View file

@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## [22.03] - 2022-03-10
### Added
- check_evomaintenanceconf : check existence and rights of evomaintenance conf file
- Added check_nrpeopensmtpd to ensure that opensmtpd is used for mailq nrpe check
- Added check_sshallowusers to ensure that AllowUsers or AllowGroups directive is present in sshd_config
- Added check_evobackup_exclude_mount to ensure that NFS mounts are excluded from backup
- Added check_etcgit to ensure that /etc is a git repository
- Added check_evolinuxsudogroup to ensure that evolinux-sudo is properly configured in sudo if group exist
- Added check_bind9munin to ensure that a plugin for bind is configured when munin is installed
- Added check_evolix_user to ensure that evolix user does not exist
- Added check_versions and its functions (download_versions, get_command, get_version, check_version, add_to_path) to ensure that custom scripts are up to date
### Changed
- Overall improvement of evocheck : reordering, splitting version and help options, adding comments, developping some functions so they are more comprehensible
- Improved check_umasksudoers to have a more complete grep
- Updated check_history to reflect the new HISTSIZE value
- Renamed check_tmp1777 and check_root0700 respectively to check_tmp_1777 and check_root_0700
- Improved check_tmp_1777, check_root_0700, check_usrsharescripts in the way the folders rights are checked
### Fixed
- Fixed check_uptime : it didn't work at all, and tried to get uptime in the wrong way
- Fixed check_evomaintenanceusers : sudo is not used for the evomaintenance trap, doas is ; and users were not found the better way
### Removed
- Removed empty check_pfcustom
## [21.10] - 2021-10-07 ## [21.10] - 2021-10-07
### Fixed ### Fixed

View file

@ -3,67 +3,46 @@
# EvoCheck # EvoCheck
# Script to verify compliance of an OpenBSD server powered by Evolix # Script to verify compliance of an OpenBSD server powered by Evolix
readonly VERSION="21.10" readonly VERSION="22.03"
# Disable LANG* # base functions
export LANG=C show_version() {
export LANGUAGE=C
# Default return code : 0 = no error
RC=0
# Verbose function
verbose() {
msg="${1:-$(cat /dev/stdin)}"
[ "${VERBOSE}" -eq 1 ] && [ -n "${msg}" ] && echo "${msg}"
}
# Source configuration file
test -f /etc/evocheck.cf && . /etc/evocheck.cf
# Functions
show_help() {
cat <<END cat <<END
NAME: evocheck version ${VERSION}
evocheck - a system configuration verification tool
VERSION: Copyright 2009-2021 Evolix <info@evolix.fr>,
${VERSION} Romain Dessort <rdessort@evolix.fr>,
Benoit Série <bserie@evolix.fr>,
Gregory Colpart <reg@evolix.fr>,
Jérémy Lecour <jlecour@evolix.fr>,
Tristan Pilat <tpilat@evolix.fr>,
Victor Laborie <vlaborie@evolix.fr>,
Jérémy Dubois <jdubois@evolix.fr>
and others.
DESCRIPTION: evocheck comes with ABSOLUTELY NO WARRANTY. This is free software,
A script that verifies Evolix conventions on OpenBSD servers and you are welcome to redistribute it under certain conditions.
See the GNU General Public License v3.0 for details.
AUTHORS:
Benoit Serie <bserie@evolix.fr>
Gregory Colpart <reg@evolix.fr>
Jeremy Dubois <jdubois@evolix.fr>
Jeremy Lecour <jlecour@evolix.fr>
Ludovic Poujol <lpoujol@evolix.fr>
Romain Dessort <rdessort@evolix.fr>
Tristan Pilat <tpilat@evolix.fr>
Victor Laborie <vlaborie@evolix.fr>
USAGE: evocheck
or evocheck --cron
or evocheck --quiet
or evocheck --verbose
OPTIONS:
--cron disable a few checks
-v, --verbose increase verbosity of checks
-q, --quiet nothing is printed on stdout nor stderr
-h, --help, --version print this message and exit
COPYRIGHT:
evocheck comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
See the GNU General Public License v3.0 for details. 2009-2020
END END
} }
show_help() {
cat <<END
evocheck is a script that verifies Evolix conventions on OpenBSD servers.
Usage: evocheck
or evocheck --cron
or evocheck --quiet
or evocheck --verbose
Options
--cron disable a few checks
-v, --verbose increase verbosity of checks
-q, --quiet nothing is printed on stdout nor stderr
-h, --help print this message and exit
--version print version and exit
END
}
is_installed(){ is_installed(){
for pkg in "$@"; do for pkg in "$@"; do
pkg_info | grep -q $pkg || return 1 pkg_info | grep -q $pkg || return 1
@ -71,6 +50,7 @@ is_installed(){
} }
# logging # logging
failed() { failed() {
check_name=$1 check_name=$1
shift shift
@ -86,41 +66,31 @@ failed() {
fi fi
} }
# check functions
# If --cron is passed, ignore some checks.
if [ "$1" = "--cron" ]; then
IS_KERNELUPTODATE=0
IS_UPTIME=0
fi
check_umasksudoers(){ check_umasksudoers(){
grep -E -qr "umask=0077" /etc/sudoers* || failed "IS_UMASKSUDOERS" "sudoers must set umask to 0077" grep -Rq "^Defaults.*umask=0077" /etc/sudoers* || failed "IS_UMASKSUDOERS" "sudoers must set umask to 0077"
} }
check_tmpnoexec(){ check_tmpnoexec(){
mount | grep "on /tmp" | grep -q noexec || failed "IS_TMPNOEXEC" "/tmp should be mounted with the noexec option" mount | grep "on /tmp" | grep -q noexec || failed "IS_TMPNOEXEC" "/tmp should be mounted with the noexec option"
} }
check_softdep(){ check_softdep(){
if [ $(grep -c softdep /etc/fstab) -ne $(grep -c ffs /etc/fstab) ]; then if [ $(grep -c softdep /etc/fstab) -ne $(grep -c ffs /etc/fstab) ]; then
failed "IS_SOFTDEP" "All partitions should have the softdep option" failed "IS_SOFTDEP" "All partitions should have the softdep option"
fi fi
} }
check_noatime(){ check_noatime(){
if [ $(mount | grep -c noatime) -ne $(grep ffs /etc/fstab | grep -vc ^\#) ]; then if [ $(mount | grep -c noatime) -ne $(grep ffs /etc/fstab | grep -vc ^\#) ]; then
failed "IS_NOATIME" "All partitions should be mounted with the noatime option" failed "IS_NOATIME" "All partitions should be mounted with the noatime option"
fi fi
} }
check_tmoutprofile(){ check_tmoutprofile(){
if [ -f /etc/skel/.profile ]; then if [ -f /etc/skel/.profile ]; then
grep -q TMOUT= /etc/skel/.profile /root/.profile || failed "IS_TMOUTPROFILE" "In order to fix, add 'export TMOUT=36000' to both /etc/skel/.profile and /root/.profile files" grep -q TMOUT= /etc/skel/.profile /root/.profile || failed "IS_TMOUTPROFILE" "Add 'export TMOUT=36000' to both /etc/skel/.profile and /root/.profile files"
else else
failed "IS_TMOUTPROFILE" "File /etc/skel/.profile does not exist. Both /etc/skel/.profile and /root/.profile should contain at least 'export TMOUT=36000'" failed "IS_TMOUTPROFILE" "File /etc/skel/.profile does not exist. Both /etc/skel/.profile and /root/.profile should contain at least 'export TMOUT=36000'"
fi fi
} }
check_raidok(){ check_raidok(){
egrep 'sd.*RAID' /var/run/dmesg.boot 1> /dev/null 2>&1 egrep 'sd.*RAID' /var/run/dmesg.boot 1> /dev/null 2>&1
RESULT=$? RESULT=$?
@ -132,7 +102,6 @@ check_raidok(){
fi fi
fi fi
} }
check_evobackup(){ check_evobackup(){
if [ -f /etc/daily.local ]; then if [ -f /etc/daily.local ]; then
grep -qE "^sh /usr/share/scripts/zzz_evobackup" /etc/daily.local || failed "IS_EVOBACKUP" "Make sure 'sh /usr/share/scripts/zzz_evobackup' is present and activated in /etc/daily.local" grep -qE "^sh /usr/share/scripts/zzz_evobackup" /etc/daily.local || failed "IS_EVOBACKUP" "Make sure 'sh /usr/share/scripts/zzz_evobackup' is present and activated in /etc/daily.local"
@ -140,7 +109,6 @@ check_evobackup(){
failed "IS_EVOBACKUP" "Make sure /etc/daily.local exists and 'sh /usr/share/scripts/zzz_evobackup' is present and activated in /etc/daily.local" failed "IS_EVOBACKUP" "Make sure /etc/daily.local exists and 'sh /usr/share/scripts/zzz_evobackup' is present and activated in /etc/daily.local"
fi fi
} }
check_uptodate(){ check_uptodate(){
if [ $(command -v syspatch) ]; then if [ $(command -v syspatch) ]; then
if syspatch -c | egrep "." 1> /dev/null 2>&1; then if syspatch -c | egrep "." 1> /dev/null 2>&1; then
@ -148,13 +116,12 @@ check_uptodate(){
fi fi
fi fi
} }
check_uptime(){ check_uptime(){
if [ $(uptime | cut -d" " -f 4) -gt 365 ]; then let "uptime = $(date +"%s") - $(sysctl -n kern.boottime)"
failed "IS_UPTIME" "The server is running for more than a year!" if [ "$uptime" -gt "$(( 2*365*24*60*60 ))" ]; then
failed "IS_UPTIME" "The server has an uptime of more than 2 years, reboot on new kernel advised"
fi fi
} }
check_backupuptodate(){ check_backupuptodate(){
backup_dir="/home/backup" backup_dir="/home/backup"
if [ -d "${backup_dir}" ]; then if [ -d "${backup_dir}" ]; then
@ -175,11 +142,14 @@ check_backupuptodate(){
failed "IS_BACKUPUPTODATE" "${backup_dir}/ is missing" failed "IS_BACKUPUPTODATE" "${backup_dir}/ is missing"
fi fi
} }
check_gitperms() {
check_gitperms(){ GIT_DIR="/etc/.git"
test -d /etc/.git && [ "$(stat -f %p /etc/.git/)" = "40700" ] || failed "IS_GITPERMS" "The directiry /etc/.git sould be in 700" if test -d $GIT_DIR; then
expected="40700"
actual=$(stat -f "%p" $GIT_DIR)
[ "$expected" = "$actual" ] || failed "IS_GITPERMS" "$GIT_DIR must be 700"
fi
} }
check_carpadvbase(){ check_carpadvbase(){
if ls /etc/hostname.carp* 1> /dev/null 2>&1; then if ls /etc/hostname.carp* 1> /dev/null 2>&1; then
bad_advbase=0 bad_advbase=0
@ -193,7 +163,6 @@ check_carpadvbase(){
fi fi
fi fi
} }
check_carppreempt(){ check_carppreempt(){
if ls /etc/hostname.carp* 1> /dev/null 2>&1; then if ls /etc/hostname.carp* 1> /dev/null 2>&1; then
preempt=$(sysctl net.inet.carp.preempt | cut -d"=" -f2) preempt=$(sysctl net.inet.carp.preempt | cut -d"=" -f2)
@ -207,7 +176,6 @@ check_carppreempt(){
fi fi
fi fi
} }
check_rebootmail(){ check_rebootmail(){
if [ -f /etc/rc.local ]; then if [ -f /etc/rc.local ]; then
grep -qE '^date \| mail -s "boot/reboot of' /etc/rc.local || failed "IS_REBOOTMAIL" "Make sure the line 'date | mail -s \"boot/reboot of \$hostname' is present in the /etc/rc.local file!" grep -qE '^date \| mail -s "boot/reboot of' /etc/rc.local || failed "IS_REBOOTMAIL" "Make sure the line 'date | mail -s \"boot/reboot of \$hostname' is present in the /etc/rc.local file!"
@ -215,111 +183,106 @@ check_rebootmail(){
failed "IS_REBOOTMAIL" "Make sure /etc/rc.local exist and 'date | mail -s \"boot/reboot of \$hostname' is present!" failed "IS_REBOOTMAIL" "Make sure /etc/rc.local exist and 'date | mail -s \"boot/reboot of \$hostname' is present!"
fi fi
} }
check_pfenabled(){ check_pfenabled(){
if pfctl -si | grep Disabled 1> /dev/null 2>&1; then if pfctl -si | grep Disabled 1> /dev/null 2>&1; then
failed "IS_PFENABLED" "PF is disabled! Make sure pf=NO is absent from /etc/rc.conf.local and carefully run pfctl -e" failed "IS_PFENABLED" "PF is disabled! Make sure pf=NO is absent from /etc/rc.conf.local and carefully run pfctl -e"
fi fi
} }
check_pfcustom(){
}
check_wheel(){ check_wheel(){
if [ -f /etc/sudoers ]; then if [ -f /etc/sudoers ]; then
grep -qE "^%wheel.*$" /etc/sudoers || failed "IS_WHEEL" "" grep -qE "^%wheel.*$" /etc/sudoers || failed "IS_WHEEL" ""
fi fi
} }
check_pkgmirror(){ check_pkgmirror(){
grep -qE "^https://cdn\.openbsd\.org/pub/OpenBSD" /etc/installurl || failed "IS_PKGMIRROR" "Check whether the right repo is present in the /etc/installurl file" grep -qE "^https://cdn\.openbsd\.org/pub/OpenBSD" /etc/installurl || failed "IS_PKGMIRROR" "Check whether the right repo is present in the /etc/installurl file"
} }
check_history(){ check_history(){
file=/root/.profile file=/root/.profile
grep -qE "^HISTFILE=\$HOME/.histfile" $file && grep -qE "^export HISTSIZE=10000" $file || failed "IS_HISTORY" "Make sure both 'HISTFILE=$HOME/.histfile' and 'export HISTSIZE=10000' are present in /root/.profile" grep -qE "^HISTFILE=\$HOME/.histfile" $file && grep -qE "^export HISTSIZE=100000" $file || failed "IS_HISTORY" "Make sure both 'HISTFILE=$HOME/.histfile' and 'export HISTSIZE=100000' are present in /root/.profile"
} }
check_vim(){ check_vim(){
if ! is_installed vim; then if ! is_installed vim; then
failed "IS_VIM" "vim is not installed! Please add with pkg_add vim" failed "IS_VIM" "vim is not installed! Please add with pkg_add vim"
fi fi
} }
check_ttyc0secure(){ check_ttyc0secure(){
grep -Eqv "^ttyC0.*secure$" /etc/ttys || failed "IS_TTYC0SECURE" "First tty should be secured" grep -Eqv "^ttyC0.*secure$" /etc/ttys || failed "IS_TTYC0SECURE" "First tty should be secured"
} }
check_customsyslog(){ check_customsyslog(){
grep -q EvoBSD /etc/newsyslog.conf || failed "IS_CUSTOMSYSLOG" "" grep -q EvoBSD /etc/newsyslog.conf || failed "IS_CUSTOMSYSLOG" ""
} }
check_sudomaint(){ check_sudomaint(){
file=/etc/sudoers file=/etc/sudoers
grep -q "Cmnd_Alias MAINT = /usr/share/scripts/evomaintenance.sh" $file \ grep -q "Cmnd_Alias MAINT = /usr/share/scripts/evomaintenance.sh" $file \
&& grep -q "%wheel ALL=NOPASSWD: MAINT" $file \ && grep -q "%wheel ALL=NOPASSWD: MAINT" $file \
|| failed "IS_SUDOMAINT" "" || failed "IS_SUDOMAINT" ""
} }
check_nrpe(){ check_nrpe(){
if ! is_installed monitoring-plugins || ! is_installed nrpe; then if ! is_installed monitoring-plugins || ! is_installed nrpe; then
failed "IS_NRPE" "nrpe and/or monitoring-plugins are not installed! Please add with pkg_add nrpe monitoring-plugins" failed "IS_NRPE" "nrpe and/or monitoring-plugins are not installed! Please add with pkg_add nrpe monitoring-plugins"
fi fi
} }
check_rsync(){ check_rsync(){
if ! is_installed rsync; then if ! is_installed rsync; then
failed "IS_RSYNC" "rsync is not installed! Please add with pkg_add rsync" failed "IS_RSYNC" "rsync is not installed! Please add with pkg_add rsync"
fi fi
} }
check_cronpath(){ check_cronpath(){
grep -q "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/share/scripts" /var/cron/tabs/root || failed "IS_CRONPATH" "" grep -q "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/share/scripts" /var/cron/tabs/root || failed "IS_CRONPATH" ""
} }
check_tmp_1777(){
check_tmp1777(){ actual=$(stat -f "%p" /tmp)
ls -ld /tmp | grep -q drwxrwxrwt || failed "IS_TMP_1777" "" expected="41777"
test "$expected" = "$actual" || failed "IS_TMP_1777" "/tmp must be 1777"
} }
check_root_0700(){
check_root0700(){ actual=$(stat -f "%p" /root)
ls -ld /root | grep -q drwx------ || failed "IS_ROOT_0700" "" expected="40700"
test "$expected" = "$actual" || failed "IS_ROOT_0700" "/root must be 700"
} }
check_usrsharescripts(){ check_usrsharescripts(){
ls -ld /usr/share/scripts | grep -q drwx------ || failed "IS_USRSHARESCRIPTS" "" actual=$(stat -f "%p" /usr/share/scripts)
expected="40700"
test "$expected" = "$actual" || failed "IS_USRSHARESCRIPTS" "/usr/share/scripts must be 700"
} }
check_sshpermitrootno() { check_sshpermitrootno() {
grep -qE ^PermitRoot /etc/ssh/sshd_config && ( grep -E -qi "PermitRoot.*no" /etc/ssh/sshd_config || failed "IS_SSHPERMITROOTNO" "" ) if grep -q "^PermitRoot" /etc/ssh/sshd_config; then
grep -E -qi "PermitRoot.*no" /etc/ssh/sshd_config \
|| failed "IS_SSHPERMITROOTNO" "PermitRoot should be set at no"
fi
} }
check_evomaintenanceusers(){ check_evomaintenanceusers(){
# Can be changed in evocheck.cf users=$(getent group evolinux-sudo | cut -d':' -f4 | tr ',' ' ')
homeDir=${homeDir:-/home} for user in $users; do
sudoers="/etc/sudoers" user_home=$(getent passwd "$user" | cut -d: -f6)
for i in $( (grep "^User_Alias *ADMIN" $sudoers | cut -d= -f2 | tr -d " "; grep ^sudo /etc/group |cut -d: -f 4) | tr "," "\n" |sort -u); do if [ -n "$user_home" ] && [ -d "$user_home" ]; then
grep -qs "^trap.*sudo.*evomaintenance.sh" ${homeDir}/${i}/.*profile if ! grep -qs "^trap.*doas.*evomaintenance.sh" "${user_home}"/.*profile; then
if [ $? != 0 ]; then echo "IS_EVOMAINTENANCEUSERS" "${user} doesn't have an evomaintenance trap"
failed "IS_EVOMAINTENANCEUSERS" "$i doesn't have evomaintenance trap!" test "${VERBOSE}" = 1 || break
fi
fi fi
done done
} }
check_evomaintenanceconf(){ check_evomaintenanceconf(){
file=/etc/evomaintenance.cf f=/etc/evomaintenance.cf
( test -e $file \ if [ -e "$f" ]; then
&& test $(stat -f %p $file) = "100600" \ perms=$(stat -f "%p" $f)
&& grep "^export PGPASSWORD" $file |grep -qv "your-passwd" \ test "$perms" = "100600" || echo "IS_EVOMAINTENANCECONF" "Wrong permissions on \`$f' ($perms instead of 100600)"
&& grep "^PGDB" $file |grep -qv "your-db" \
&& grep "^PGTABLE" $file |grep -qv "your-table" \
&& grep "^PGHOST" $file |grep -qv "your-pg-host" \
&& grep "^FROM" $file |grep -qv "jdoe@example.com" \
&& grep "^FULLFROM" $file |grep -qv "John Doe <jdoe@example.com>" \
&& grep "^URGENCYFROM" $file |grep -qv "mama.doe@example.com" \
&& grep "^URGENCYTEL" $file |grep -qv "06.00.00.00.00" \
&& grep "^REALM" $file |grep -qv "example.com" ) || failed "IS_EVOMAINTENANCECONF" ""
}
{ grep "^export PGPASSWORD" $f | grep -qv "your-passwd" \
&& grep "^PGDB" $f | grep -qv "your-db" \
&& grep "^PGTABLE" $f | grep -qv "your-table" \
&& grep "^PGHOST" $f | grep -qv "your-pg-host" \
&& grep "^FROM" $f | grep -qv "jdoe@example.com" \
&& grep "^FULLFROM" $f | grep -qv "John Doe <jdoe@example.com>" \
&& grep "^URGENCYFROM" $f | grep -qv "mama.doe@example.com" \
&& grep "^URGENCYTEL" $f | grep -qv "06.00.00.00.00" \
&& grep "^REALM" $f | grep -qv "example.com"
} || echo "IS_EVOMAINTENANCECONF" "evomaintenance is not correctly configured"
else
echo "IS_EVOMAINTENANCECONF" "Configuration file \`$f' is missing"
fi
}
check_sync(){ check_sync(){
if ifconfig carp | grep carp 1> /dev/null 2>&1; then if ifconfig carp | grep carp 1> /dev/null 2>&1; then
sync_script=/usr/share/scripts/sync.sh sync_script=/usr/share/scripts/sync.sh
@ -328,7 +291,6 @@ check_sync(){
fi fi
fi fi
} }
check_defaultroute(){ check_defaultroute(){
if [ -f /etc/mygate ]; then if [ -f /etc/mygate ]; then
file_route=$(cat /etc/mygate) file_route=$(cat /etc/mygate)
@ -340,7 +302,6 @@ check_defaultroute(){
failed "IS_DEFAULTROUTE" "The file /etc/mygate does not exist. Make sure you have the same default route in this file as the one currently in use." failed "IS_DEFAULTROUTE" "The file /etc/mygate does not exist. Make sure you have the same default route in this file as the one currently in use."
fi fi
} }
check_ntp(){ check_ntp(){
if grep -q "server ntp.evolix.net" /etc/ntpd.conf; then if grep -q "server ntp.evolix.net" /etc/ntpd.conf; then
if [ $(wc -l /etc/ntpd.conf | awk '{print $1}') -ne 1 ]; then if [ $(wc -l /etc/ntpd.conf | awk '{print $1}') -ne 1 ]; then
@ -350,13 +311,11 @@ check_ntp(){
failed "IS_NTP" "The configuration in /etc/ntpd.conf is not compliant. It should contains \"server ntp.evolix.net\"." failed "IS_NTP" "The configuration in /etc/ntpd.conf is not compliant. It should contains \"server ntp.evolix.net\"."
fi fi
} }
check_openvpncronlog(){ check_openvpncronlog(){
if /etc/rc.d/openvpn check > /dev/null 2>&1; then if /etc/rc.d/openvpn check > /dev/null 2>&1; then
grep -q 'cp /var/log/openvpn.log /var/log/openvpn.log.$(date +\\%F) && echo "$(date +\\%F. .\\%R) - logfile turned over via cron" > /var/log/openvpn.log && gzip /var/log/openvpn.log.$(date +\\%F) && find /var/log/ -type f -name "openvpn.log.\*" -mtime .365 -exec rm {} \\+' /var/cron/tabs/root || failed "IS_OPENVPNCRONLOG" "OpenVPN is enabled but there is no log rotation in the root crontab, or the cron is not up to date (OpenVPN log rotation in newsyslog is not used because a restart is needed)." grep -q 'cp /var/log/openvpn.log /var/log/openvpn.log.$(date +\\%F) && echo "$(date +\\%F. .\\%R) - logfile turned over via cron" > /var/log/openvpn.log && gzip /var/log/openvpn.log.$(date +\\%F) && find /var/log/ -type f -name "openvpn.log.\*" -mtime .365 -exec rm {} \\+' /var/cron/tabs/root || failed "IS_OPENVPNCRONLOG" "OpenVPN is enabled but there is no log rotation in the root crontab, or the cron is not up to date (OpenVPN log rotation in newsyslog is not used because a restart is needed)."
fi fi
} }
check_carpadvskew(){ check_carpadvskew(){
if ls /etc/hostname.carp* 1> /dev/null 2>&1; then if ls /etc/hostname.carp* 1> /dev/null 2>&1; then
for carp in $(ifconfig carp | grep ^carp | awk '{print $1}' | tr -d ":"); do for carp in $(ifconfig carp | grep ^carp | awk '{print $1}' | tr -d ":"); do
@ -379,7 +338,152 @@ check_carpadvskew(){
done done
fi fi
} }
check_nrpeopensmtpd() {
grep -Rq "^command.*check_mailq.pl -M opensmtpd" /etc/nrpe.* || failed "IS_NRPE_OPENSMTPD" "NRPE \"check_mailq\" is not configured for opensmtpd."
}
check_sshallowusers() {
grep -E -qir "(AllowUsers|AllowGroups)" /etc/ssh/sshd_config || failed "IS_SSHALLOWUSERS" "Missing AllowUsers or AllowGroups directive in sshd_config"
}
check_evobackup_exclude_mount() {
excludes_file=$(mktemp)
trap "rm -f ${excludes_file}" 0
for evobackup_file in $(grep -Eo "/usr/share/scripts/zzz_evobackup.*" /etc/daily.local | grep -v "^#" | awk '{print $1}'); do
grep -- "--exclude " "${evobackup_file}" | grep -E -o "\"[^\"]+\"" | tr -d '"' > "${excludes_file}"
not_excluded=$(mount | grep "type nfs" | awk '{print $3}' | grep -v -f "${excludes_file}")
for mount in ${not_excluded}; do
failed "IS_EVOBACKUP_EXCLUDE_MOUNT" "${mount} is not excluded from ${evobackup_file} backup script"
done
done
rm -rf "${excludes_file}"
}
check_etcgit() {
export GIT_DIR="/etc/.git" GIT_WORK_TREE="/etc"
git rev-parse --is-inside-work-tree > /dev/null 2>&1 || failed "IS_ETCGIT" "/etc is not a git repository"
}
check_evolinuxsudogroup() {
if grep -q "^evolinux-sudo:" /etc/group; then
grep -qE "^%evolinux-sudo ALL ?= ?\(ALL\) SETENV: ALL" /etc/sudoers || failed "IS_EVOLINUXSUDOGROUP" "Missing evolinux-sudo directive in sudoers file"
fi
}
check_bind9munin() {
if is_installed isc-bind; then
{ test -L /etc/munin/plugins/bind9 \
&& test -e /etc/munin/plugin-conf.d/bind9;
} || failed "IS_BIND9MUNIN" "missing bind plugin for munin"
fi
}
check_evolix_user() {
grep -q -E "^evolix:" /etc/passwd && failed "IS_EVOLIX_USER" "evolix user should not exist"
}
download_versions() {
local file
file=${1:-}
## The file is supposed to list programs : each on a line, then its latest version number
## Examples:
# evoacme 21.06
# evomaintenance 0.6.4
versions_url="https://upgrades.evolix.org/versions-openbsd"
# fetch timeout, in seconds
timeout=10
if command -v curl > /dev/null; then
curl -k --max-time ${timeout} --fail --silent --output "${versions_file}" "${versions_url}"
# "-k" required until OpenBSD 6.8
elif command -v wget > /dev/null; then
wget --timeout=${timeout} --quiet "${versions_url}" -O "${versions_file}"
elif command -v GET; then
GET -t ${timeout}s "${versions_url}" > "${versions_file}"
else
failed "IS_VERSIONS_CHECK" "failed to find curl, wget or GET"
fi
test "$?" -eq 0 || failed "IS_VERSIONS_CHECK" "failed to download ${versions_url} to ${versions_file}"
}
get_command() {
local program
program=${1:-}
case "${program}" in
## Special cases where the program name is different than the command name
evocheck) echo "${0}" ;;
evomaintenance) command -v "evomaintenance.sh" ;;
motd-carp-state) command -v "motd-carp-state.sh" ;;
## General case, where the program name is the same as the command name
*) command -v "${program}" ;;
esac
}
get_version() {
local program
local command
program=${1:-}
command=${2:-}
case "${program}" in
## Special case if `command --version => 'command` is not the standard way to get the version
# my_command)
# /path/to/my_command --get-version
# ;;
motd-carp-state)
grep '^VERSION=' "${command}" | head -1 | cut -d '=' -f 2
;;
## General case to get the version
*) ${command} --version 2> /dev/null | head -1 | cut -d ' ' -f 3 ;;
esac
}
check_version() {
local program
local expected_version
program=${1:-}
expected_version=${2:-}
command=$(get_command "${program}")
if [ -n "${command}" ]; then
actual_version=$(get_version "${program}" "${command}")
# printf "program:%s expected:%s actual:%s\n" "${program}" "${expected_version}" "${actual_version}"
if [ -z "${actual_version}" ]; then
failed "IS_VERSIONS_CHECK" "failed to lookup actual version of ${program}"
elif [ "${actual_version}" = "${expected_version}" ]; then
: # Version check OK ; to check first because of the way the check works
elif [ "$(echo ${actual_version}\\n${expected_version} | sort -V | head -n 1)" = "${actual_version}" ]; then
failed "IS_VERSIONS_CHECK" "${program} version ${actual_version} is older than expected version ${expected_version}"
elif [ "$(echo ${actual_version}\\n${expected_version} | sort -V | head -n 1)" = "${expected_version}" ]; then
failed "IS_VERSIONS_CHECK" "${program} version ${actual_version} is newer than expected version ${expected_version}, you should update your index."
fi
fi
}
add_to_path() {
local new_path
new_path=${1:-}
echo "$PATH" | grep -qF "${new_path}" || export PATH="${PATH}:${new_path}"
}
check_versions() {
versions_file=$(mktemp -p /tmp "evocheck-versions.XXXXXXXX")
trap "rm -f ${versions_file}" 0
download_versions "${versions_file}"
add_to_path "/usr/share/scripts"
grep -v '^ *#' < "${versions_file}" | while IFS= read -r line; do
local program
local version
program=$(echo "${line}" | cut -d ' ' -f 1)
version=$(echo "${line}" | cut -d ' ' -f 2)
if [ -n "${program}" ]; then
if [ -n "${version}" ]; then
check_version "${program}" "${version}"
else
failed "IS_VERSIONS_CHECK" "failed to lookup expected version for ${program}"
fi
fi
done
rm -f "${versions_file}"
}
main() { main() {
# Default return code : 0 = no error # Default return code : 0 = no error
@ -400,7 +504,6 @@ main() {
test "${IS_CARPPREEMPT:=1}" = 1 && check_carppreempt test "${IS_CARPPREEMPT:=1}" = 1 && check_carppreempt
test "${IS_REBOOTMAIL:=1}" = 1 && check_rebootmail test "${IS_REBOOTMAIL:=1}" = 1 && check_rebootmail
test "${IS_PFENABLED:=1}" = 1 && check_pfenabled test "${IS_PFENABLED:=1}" = 1 && check_pfenabled
test "${IS_PFCUSTOM:=1}" = 1 && check_pfcustom
test "${IS_WHEEL:=1}" = 1 && check_wheel test "${IS_WHEEL:=1}" = 1 && check_wheel
test "${IS_PKGMIRROR:=1}" = 1 && check_pkgmirror test "${IS_PKGMIRROR:=1}" = 1 && check_pkgmirror
test "${IS_HISTORY:=1}" = 1 && check_history test "${IS_HISTORY:=1}" = 1 && check_history
@ -411,8 +514,8 @@ main() {
test "${IS_NRPE:=1}" = 1 && check_nrpe test "${IS_NRPE:=1}" = 1 && check_nrpe
test "${IS_RSYNC:=1}" = 1 && check_rsync test "${IS_RSYNC:=1}" = 1 && check_rsync
test "${IS_CRONPATH:=1}" = 1 && check_cronpath test "${IS_CRONPATH:=1}" = 1 && check_cronpath
test "${IS_TMP_1777:=1}" = 1 && check_tmp1777 test "${IS_TMP_1777:=1}" = 1 && check_tmp_1777
test "${IS_ROOT_0700:=1}" = 1 && check_root0700 test "${IS_ROOT_0700:=1}" = 1 && check_root_0700
test "${IS_USRSHARESCRIPTS:=1}" = 1 && check_usrsharescripts test "${IS_USRSHARESCRIPTS:=1}" = 1 && check_usrsharescripts
test "${IS_SSHPERMITROOTNO:=1}" = 1 && check_sshpermitrootno test "${IS_SSHPERMITROOTNO:=1}" = 1 && check_sshpermitrootno
test "${IS_EVOMAINTENANCEUSERS:=1}" = 1 && check_evomaintenanceusers test "${IS_EVOMAINTENANCEUSERS:=1}" = 1 && check_evomaintenanceusers
@ -422,17 +525,37 @@ main() {
test "${IS_NTP:=1}" = 1 && check_ntp test "${IS_NTP:=1}" = 1 && check_ntp
test "${IS_OPENVPNCRONLOG:=1}" = 1 && check_openvpncronlog test "${IS_OPENVPNCRONLOG:=1}" = 1 && check_openvpncronlog
test "${IS_CARPADVSKEW:=1}" = 1 && check_carpadvskew test "${IS_CARPADVSKEW:=1}" = 1 && check_carpadvskew
test "${IS_NRPE_OPENSMTPD:=1}" = 1 && check_nrpeopensmtpd
test "${IS_SSHALLOWUSERS:=1}" = 1 && check_sshallowusers
test "${IS_EVOBACKUP_EXCLUDE_MOUNT:=1}" = 1 && check_evobackup_exclude_mount
test "${IS_ETCGIT:=1}" = 1 && check_etcgit
test "${IS_EVOLINUXSUDOGROUP:=1}" = 1 && check_evolinuxsudogroup
test "${IS_BIND9MUNIN:=1}" = 1 && check_bind9munin
test "${IS_EVOLIX_USER:=1}" = 1 && check_evolix_user
test "${IS_VERSIONS_CHECK:=1}" = 1 && check_versions
exit ${RC} exit ${RC}
} }
# Disable LANG*
export LANG=C
export LANGUAGE=C
# Source configuration file
test -f /etc/evocheck.cf && . /etc/evocheck.cf
# Parse options # Parse options
# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a # based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
while :; do while :; do
case $1 in case $1 in
-h|-\?|--help|--version) -h|-\?|--help)
show_help show_help
exit 0 exit 0
;; ;;
--version)
show_version
exit 0
;;
--cron) --cron)
IS_KERNELUPTODATE=0 IS_KERNELUPTODATE=0
IS_UPTIME=0 IS_UPTIME=0