Compare commits

...

106 Commits

Author SHA1 Message Date
Jérémy Lecour 202db682a0
IS_SYSLOGCONF: modern and legacy tests 2024-02-05 19:17:33 +01:00
William Hirigoyen 25b00f6fa7 Fix errors in some LXC checks: list only active LXC containers, add conditions to filter containers that are not in evo-standards. 2024-01-31 14:50:28 +01:00
Jérémy Lecour c4c8dd2112
IS_SYSLOGCONF: better detection 2024-01-26 16:17:34 +01:00
David Prevot 5536e8f6ec Fix recent release dates 2024-01-03 17:41:05 +01:00
David Prevot d14a6d52a3 Linux - Release 24.01 2024-01-03 17:30:13 +01:00
Mathieu Trossevin fba4dc75c3 fix(IS_EVOBACKUP_EXCLUDE_MOUNT): correctly treat old versions of evobackup
This commit fix #150

Prior to this older versions of evobackup without `VERSION=` in them
would be treated as not having any exclude whatsoever as the `else`
block was only inside of the `if grep -q  "^VERSION="
"${evobackup_file}"` block.

Now the treatment of old evobackup scripts is done if there isn't a
`VERSION=` in the script or if the version is older than 22.12.
2024-01-03 15:13:23 +01:00
David Prevot 1fc94ec4f1 Changelog for previous entries 2023-12-13 17:51:10 +01:00
David Prevot 2df62afa21 IS_DEBIANSECURITY_LXC: Don’t test older than Debian 9 containers
We use eLTS for Jessie without security, that has been archived and
signed with an expired key.
2023-12-13 17:49:35 +01:00
David Prevot ff5f7ec399 IS_KERNELUPTODATE: Address false positive in case of kernel removal
If a kernel is removed, then grub is updated. Try to check the actual
kernel files instead of any file in /boot.
2023-12-13 17:06:52 +01:00
David Prevot f64176db21 Add IS_BACKPORTS_VERSION 2023-12-13 17:02:55 +01:00
David Prevot 14e56cd575 check_broadcomfirmware: use apt-policy (making it useful before Debian 10) 2023-12-05 15:17:25 +01:00
Alexis Ben Miloud--Josselin 27347f7342 check_sshpermitrootno: Always specify lport
When sshd listens two ports (usually 22 and another one), the sshd
-T command will fail if lport is not specified.

This commit also simplifies the if-elif block.
2023-12-01 09:45:06 +01:00
Alexis Ben Miloud--Josselin e27bb4124b Chech drbdtwoprimaries: fix false positive
Fix #151
2023-11-29 17:55:00 +01:00
Jérémy Lecour 7041505446
long options are preferred 2023-11-24 16:20:08 +01:00
David Prevot 4dbb3d030d IS_ETCGIT_LXC, IS_GITPERMS_LXC: fix path 2023-11-23 14:58:51 +01:00
Jérémy Lecour fb14549843
long options 2023-11-23 07:31:59 +01:00
Jérémy Lecour 1d995764a9
No need to escape characters if we search for a fixed string 2023-11-23 07:31:48 +01:00
David Prevot 5402fa0dee Linux - Release 23.11.1 2023-11-22 17:25:28 +01:00
David Prevot f024f9d9e8 IS_EVOBACKUP_EXCLUDE_MOUNT: fix another regression introduced in previous release 2023-11-22 17:23:59 +01:00
David Prevot e80a7781c7 Linux - Release 23.11 2023-11-22 17:02:06 +01:00
David Prevot 79a61e3046 CHANGELOG for IS_SSHALLOWUSERS change from ansible-roles 2023-11-22 16:32:35 +01:00
Alexis Ben Miloud--Josselin 95539ea38c evocheck: Fix IS_SSHALLOWUSERS condition 2023-11-22 16:30:30 +01:00
Alexis Ben Miloud--Josselin 77be2c3fe1 evocheck/ssh: add Debian 12 condition 2023-11-22 16:30:21 +01:00
David Prevot f4948b5611 linux/CHANGELOG: Update for latest changes 2023-11-22 15:51:07 +01:00
David Prevot ad85fd9784 IS_MINIFWINCLUDES, IS_NRPEPID: Change Debian release detection logic 2023-11-22 15:46:55 +01:00
David Prevot 668791208a Update IS_PHPEVOLINUXCONF for Bookworm 2023-11-22 15:33:54 +01:00
David Prevot f546fb97f0 Add IS_GITPERMS_LXC 2023-11-22 15:27:47 +01:00
David Prevot be53bce0e5 Add IS_ETCGIT_LXC 2023-11-22 15:20:59 +01:00
David Prevot f2d1f43e85 Add IS_OLDPUB_LXC 2023-11-22 15:08:02 +01:00
David Prevot f5887eb43c CHANGELOG for IS_EVOBACKUP_EXCLUDE_MOUNT fix 2023-11-22 14:38:35 +01:00
Brice Waegeneire 59a14150db fix regressions 2023-11-21 17:02:19 +01:00
David Prevot 3bf5c4fcb7 CHANGELOG for previous commits 2023-11-16 16:25:55 +01:00
David Prevot 5d15f373c2 Add IS_LXC_PHP_BAD_DEBIAN_VERSION 2023-11-16 16:23:02 +01:00
David Prevot 5fe7a88fab Add IS_SURY_LXC 2023-11-16 16:22:57 +01:00
David Prevot ad50601931 Add IS_LXC_OPENSSH 2023-11-16 15:35:00 +01:00
David Prevot 9b1946d9a0 Add IS_DEBIANSECURITY_LXC 2023-11-16 15:20:12 +01:00
David Prevot 443c232b95 [minor] tfix 2023-10-31 09:51:19 +01:00
David Prevot 868fe9d7c0 Add trixie and forky support (Debian 13, 14) 2023-10-31 09:44:46 +01:00
Jérémy Lecour 5b0a011eda
fix CHANGELOG 2023-10-27 10:31:46 +02:00
David Prevot 081a8166cc Linux - Release 23.10 2023-10-26 15:43:09 +02:00
David Prevot 8f58aa00ee IS_SURY: check that if sury is enabled, then a safeguard must be in place 2023-10-17 17:26:44 +02:00
David Prevot d92a8862e8 Add changelog entry for previous commit 2023-10-17 17:24:26 +02:00
David Prevot 1067bc6a27 Don’t recommend preferences for backports anymore
Thanks to “NotAutomatic: yes” and “ButAutomaticUpgrades: yes”, backports
packages are not pulled by default anymore since Squeeze.
2023-10-12 15:25:52 +02:00
William Hirigoyen 42cbd14123 IS_DRBDTWOPRIMARIES: check there are not 2 DRBD primaries at the same time 2023-09-20 11:26:17 +02:00
isaid ed602d9e83 Merge pull request 'fix #148' (#149) from 148 into master
Reviewed-on: #149
reviewed by Brice
2023-09-05 17:23:13 +02:00
Iliane Said b3db84a8f7 fix #148
In check_evobackup_exclude_mount function, add support for new rsync
syntax introduced in evobackup 22.12.
2023-09-05 17:20:49 +02:00
William Hirigoyen 24d3f67718 Typo 2023-08-29 17:26:25 +02:00
Jérémy Lecour 171924d99c
IS_NEWPUB: verify that the new public repository is present 2023-08-10 17:17:47 +02:00
Jérémy Lecour e09e5b3e53
IS_MINIFW: better detection of minifirewall status 2023-08-01 23:21:25 +02:00
David Prevot 7c40af199b Add IS_OLDPUB to check for pub.evolix.net 2023-07-28 09:36:24 +02:00
William Hirigoyen 152653d773 IS_BINDCHROOT: fix /etc/default path for Debian >= 11 (renamed from bind9 to named) 2023-07-17 12:15:45 +02:00
William Hirigoyen 6414a8c70e Linux - Release 23.07 2023-07-07 11:02:01 +02:00
William Hirigoyen 9d011b71b0 IS_REDIS_BACKUP: full rewrite of the check to be more flexible, and also check time of dump 2023-06-21 16:58:36 +02:00
Jérémy Dubois ad9231d9a9 OpenBSD - Release 23.06 2023-06-05 11:42:10 +02:00
Mathieu Trossevin 442d1446b5
fix(check_nrpepid): bookworm should be checked like bullseye 2023-05-04 15:20:32 +02:00
Mathieu Trossevin 90c1f854cf
chore(whitespace) 2023-05-04 15:05:47 +02:00
Mathieu Trossevin 02e2d4c5c0
fix(check_minifw): `iptables -L -n` doesn't tranlate protocol number in bookworm 2023-05-04 15:02:28 +02:00
Jérémy Dubois 4008fb3128 OpenBSD - check_mount: removed useless echo 2023-04-25 11:46:06 +02:00
Jérémy Dubois 0dae32a135 OpenBSD - check_carpadvbase and check_carppreempt: fixed indentation 2023-04-25 11:41:51 +02:00
William Hirigoyen ae797122ad Linux - Release 23.04.01 2023-04-07 11:49:57 +02:00
William Hirigoyen 96ea77b345 Linux - Release 23.04 2023-04-07 10:55:05 +02:00
Jérémy Dubois baf26b23c4 OpenBSD - check_evobackup: zzz_evobackup is now executed with bash 2023-03-22 09:56:13 +01:00
Jérémy Dubois 8d22e5ea85 OpenBSD - Change CHANGELOG format : replace "-" for lists with "*" 2023-03-01 16:02:09 +01:00
Jérémy Dubois 011c62f984 OpenBSD - check_mountfstab and check_mount : make sure all mounted partitions are in fstab and all partitions in fstab are mounted 2023-03-01 16:01:59 +01:00
William Hirigoyen da28729577 Linux - Release 23.03.01 2023-03-01 10:06:52 +01:00
William Hirigoyen 03f9a4eb15 Linux - Release 23.03 2023-03-01 09:53:56 +01:00
William Hirigoyen e21c4e8233 IS_LXC_PHP_FPM_SERVICE_UMASK_SET: fix inverted test condition. 2023-03-01 09:44:48 +01:00
William Hirigoyen 1bb00c10bd Log output and runtime config to /var/log/evocheck.log 2023-02-17 12:54:28 +01:00
William Hirigoyen ff92e3889e Log program exit 2023-02-17 12:53:31 +01:00
William Hirigoyen 97a98c8df3 Log runtime config to /var/log/evocheck.log 2023-02-17 10:48:58 +01:00
William Hirigoyen 32d2a94b71 Log output to /var/log/evocheck.log 2023-02-17 09:52:45 +01:00
William Hirigoyen e5aa1aa323 IS_LOCALHOST_IN_POSTFIX_MYDESTINATION: set grep quiet 2023-02-14 17:31:30 +01:00
William Hirigoyen c852fb188d OpenBSD - Release 23.02 2023-02-10 14:30:45 +01:00
William Hirigoyen c621431e05 OpenBSD - Release 23.02 2023-02-10 12:31:15 +01:00
William Hirigoyen ccb6c3e4f8 Linux - Release 23.02 2023-02-10 12:28:19 +01:00
William Hirigoyen 8db26f1622 OpenBDS - Release 22.12 2023-02-10 11:42:51 +01:00
William Hirigoyen e172c27f63 Linux - Release 22.12 2023-02-10 11:37:33 +01:00
William Hirigoyen 72e4b3f045 README: Add pre-tasks for release 2023-02-10 11:35:54 +01:00
William Hirigoyen 9361e5a9cf #701Update CHANGELOG 2023-02-10 10:08:00 +01:00
William Hirigoyen 6ca6686cb3 #70141 : Corriger evocheck IS_NOTUPGRADED 2023-02-10 10:05:57 +01:00
Jérémy Dubois 8ae087b799 OpenBSD - Replaced check_sudomaint with check_doasmaint and removed check_wheel 2023-02-09 16:07:14 +01:00
Jérémy Dubois 29b546584a OpenBSD - check_pkgmirror: fix openbsd mirror 2023-01-23 16:56:10 +01:00
Jérémy Lecour f1074dea2d use bash array for tmp files to cleanup 2023-01-12 17:03:35 +01:00
Jérémy Lecour f5410be26c shellcheck 2023-01-12 16:56:18 +01:00
Jérémy Lecour 3d7b2a676f whitespace 2023-01-12 16:55:08 +01:00
Jérémy Lecour 289e303801 fix syntax error 2023-01-12 16:54:42 +01:00
Jérémy Lecour be1e303040 improve readability 2023-01-12 16:53:37 +01:00
Jérémy Lecour 653f29e2d8 grep silencieux et optimisé 2023-01-12 16:48:57 +01:00
Jérémy Lecour c8ea1a3744 typos 2023-01-12 16:48:38 +01:00
William Hirigoyen f9fdc2c4ee IS_LOCALHOST_IN_POSTFIX_MYDESTINATION: fix regex and add localhost.$mydomain to check 2022-12-15 12:13:51 +01:00
David Prevot 12681b8259 Fix filename changed in 0ff69e6a07 2022-12-15 11:53:00 +01:00
William Hirigoyen 339afdcec2 Improve commit 2540c6f312 2022-12-07 16:56:01 +01:00
William Hirigoyen 6566193ebc Update CHANGELOG 2022-12-06 11:57:42 +01:00
William Hirigoyen 2540c6f312 - Add checks IS_LOCALHOST_IN_POSTFIX_MYDESTINATION, IS_SSH_FAIL2BAN_JAIL_RENAMED, IS_NO_LXC_CONTAINER, IS_LXC_PHP_FPM_SERVICE_UMASK_SET.
- Fix quote in IS_EVOBACKUP_INCS.
- Fix missing call to IS_PURGE_FAIL2BAN.
2022-12-06 11:45:14 +01:00
William Hirigoyen ff7aee8ea7 IS_REDIS_BACKUP: supports news and old default Redis backup path 2022-12-01 17:31:17 +01:00
Jérémy Dubois 1a2c3e0859 check_history: escape $HOME variable 2022-11-29 10:10:41 +01:00
Jérémy Dubois f7570ec865 check_pkgmirror: use our own openbsd mirror 2022-11-28 14:52:34 +01:00
Jérémy Lecour 8fd10bfeaf fix changelog 2022-11-27 22:06:08 +01:00
Jérémy Lecour 6c1d4f63ac Linux - Release 22.11 2022-11-27 22:01:43 +01:00
Jérémy Lecour 0ff69e6a07 Split versions for Debian 7-, 8 and 9+ 2022-11-27 21:59:05 +01:00
William Hirigoyen 2640bb1b11 Update IS_REDIS_BACKUP path to standard location (used in zzz_evobackup) 2022-11-22 15:48:20 +01:00
Alexis Ben Miloud--Josselin a232eeebcc check_redis: enable multi-instance dump check
To check multiple instances, add something like this in /etc/evocheck.cf:

    REDIS_BACKUP_PATH='/home/backup/redis/dump.rdb /home/backup/redis-instance2/dump.rdb /home/backup/redis-instance3/dump.rdb'
2022-11-14 11:08:40 +01:00
Jérémy Lecour 58a97812c6 Check Debian Security repository from apt-cache policy output
Instead of parsing files,we can ask apt-cache to list the enabled repository
and look for one labeled "Debian-Security" provided by Debian.
2022-11-11 10:18:12 +01:00
Jérémy Dubois 55b08445a7 OpenBSD - Release 22.10 2022-10-14 10:36:37 +02:00
David Prevot f74f1317b4 IS_PHPMYADMINAPACHECONF: check package config
Make sure that package configuration has not been pulled in (e.g.,
/etc/apache2/conf-available/phpmyadmin.conf could be added during an
upgrade and /etc/apache2/conf-enabled/phpmyadmin.conf during an upgrade
a few years later, and thus make phpMyAdmin available in trivial URLs.
2022-10-04 14:03:39 +02:00
Jérémy Dubois 76dfe5fa24 OpenBSD - check_ntp: comply with ntp configuration change on EvoBSD 2022-09-30 14:12:36 +02:00
7 changed files with 3420 additions and 525 deletions

View File

@ -52,7 +52,7 @@ For Debian versions : `is_debian`, `is_debian_stretch`, `is_debian_jessie`…
For packs : `is_pack_web`, `is_pack_samba`.
For installed packages : `is_installed <package> [<package>]`.
### Extact variables
### Extract variables
It's better not to inline function calls inside tests. Instead of this :
@ -72,8 +72,19 @@ test "$expected" = "$actual" || failed "IS_MINIFWPERMS"
It's better to verify that a file, a directory or a command is present before using it, even if it's true in more than 99% of situations.
## How to build the package for a new Debian release
Pre-tasks:
* Execute shellcheck on scripts `*.sh` and fix or disable the relevant checks.
* Prepare `linux/CHANGELOG` and `openbsd/CHANGELOG` for release.
* Update version number is scripts :
```
sed -i 's/VERSION=".*"/VERSION="<MAJOR>.<MINOR>"/g' */evocheck*.sh
```
On the master branch, add the last stable version with a release tag.
```
git tag -s v<VERSION> -m 'New release'

View File

@ -7,14 +7,172 @@ and this project **does not adhere to [Semantic Versioning](http://semver.org/sp
### Changed
* IS_SYSLOGCONF: better detection
### Deprecated
### Removed
### Fixed
* Fix errors in some LXC checks: list only active LXC containers, add conditions to filter containers that are not in evo-standards.
## [24.01] 2024-01-03
### Added
* IS_BACKPORTS_VERSION: check if the Backports release matches the Debian release
### Changed
* IS_BROADCOMFIRMWARE: use apt policy
* Prefer long options
* IS_POSTFIX_MYDESTINATION: use fixed string instead of escaping characters
### Fixed
* IS_EVOBACKUP_EXCLUDE_MOUNT: correctly treat old versions of evobackup
* IS_DEBIANSECURITY_LXC: dont test older than Debian 9 containers
* IS_KERNELUPTODATE: address false positive in case of kernel removal
* IS_SSHPERMITROOTNO: specify lport, avoiding failure if sshd listens to more than one port
* IS_DRBDTWOPRIMARIES: fix false positive (#151)
* IS_ETCGIT_LXC, IS_GITPERMS_LXC: fix path
## [23.11.1] 2023-11-27
### Fixed
* IS_EVOBACKUP_EXCLUDE_MOUNT: fix another regression introduced in previous release
### Security
## [23.11] 2023-11-27
### Added
* trixie and forky support (Debian 13, 14)
* IS_LXC_OPENSSH: check in openssh is installed in containers
* IS_LXC_PHP_BAD_DEBIAN_VERSION: check if php containers use the expected Debian release
* IS_DEBIANSECURITY_LXC: IS_DEBIANSECURITY in containers
* IS_SURY_LXC: IS_SURY in containers
* IS_OLDPUB_LXC: IS_OLDPUB in containers
* IS_ETCGIT_LXC: IS_ETCGIT in containers
* IS_GITPERMS_LXC: IS_GITPERMS in containers
### Changed
* IS_SSHALLOWUSERS: add Debian 12 condition
* IS_PHPEVOLINUXCONF: update for bookworm
* IS_MINIFWINCLUDES, IS_NRPEPID: Change Debian release detection logic
### Fixed
* IS_EVOBACKUP_EXCLUDE_MOUNT: fix regression introduced in previous version
## [23.10] 2023-10-26
### Added
* IS_MINIFW: better detection of minifirewall status
* IS_OLDPUB: pub.evolix.net has been supersed by pub.evolix.org since Stretch
* IS_NEWPUB: verify that the new public repository is present
* IS_DRBDTWOPRIMARIES: check there are not 2 DRBD primaries at the same time.
* IS_SURY: check that if sury is enabled, then a safeguard must be in place
### Changed
* IS_BACKPORTSCONF: does not require preferences anymore
### Fixed
* IS_BINDCHROOT: fix /etc/default path for Debian >= 11 (renamed from bind9 to named)
* IS_EVOBACKUP_EXCLUDE_MOUNT: adapt to new version of evobackup (#148)
## [23.07] 2023-07-07
### Fixed
* IS_REDIS_BACKUP: full rewrite of the check to be more flexible, and also check time of dump.
## [23.04.01] 2023-04-07
### Fixed
* IS_POSTFIX_MYDESTINATION: fix regex not working (again).
## [23.04] 2023-04-07
### Changed
* IS_LOCALHOST_IN_POSTFIX_MYDESTINATION: renamed to IS_POSTFIX_MYDESTINATION
### Fixed
* IS_POSTFIX_MYDESTINATION: fix regex not working.
## [23.03.01] 2023-03-01
### Fixed
* Fix version number.
## [23.03] 2023-03-01
### Added
* Log output and runtime config to /var/log/evocheck.log.
### Changed
### Deprecated
### Removed
### Fixed
* IS_LOCALHOST_IN_POSTFIX_MYDESTINATION: set grep quiet.
* IS_LXC_PHP_FPM_SERVICE_UMASK_SET: fix inverted test condition.
### Security
## [23.02] 2023-02-10
### Fixed
* Release with the correct version number.
## [22.12] 2023-02-10
### Added
New checks :
* IS_LOCALHOST_IN_POSTFIX_MYDESTINATION
* IS_SSH_FAIL2BAN_JAIL_RENAMED
* IS_NO_LXC_CONTAINER
* IS_LXC_PHP_FPM_SERVICE_UMASK_SET
### Changed
* Use bash array for tmp files to cleanup.
### Fixed
* IS_EVOBACKUP_INCS: fix quote.
* IS_PURGE_FAIL2BAN: fix function never called in main().
* IS_NOTUPGRADED: silence "grep: (...) binary file matches" messages.
## [22.11] 2022-11-27
### Added
* New script for Debian 7 and earlier
* New script for Debian 8
* IS_PHPMYADMINAPACHECONF: check that package configuration has not been pulled in
### Changed
* IS_DEBIANSECURITY: check Debian Security repository from apt-cache policy output
### Removed
* Main script is not compatible with Debian 8 and earlier anymore
## [22.09] 2022-09-14
### Fixed

1307
linux/evocheck.jessie.sh Executable file
View File

@ -0,0 +1,1307 @@
#!/bin/bash
# EvoCheck
# Script to verify compliance of a Linux (Debian) server
# powered by Evolix
VERSION="24.01"
readonly VERSION
# base functions
show_version() {
cat <<END
evocheck version ${VERSION} (Jessie)
Copyright 2009-2022 Evolix <info@evolix.fr>,
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>,
Alexis Ben Miloud--Josselin <abenmiloud@evolix.fr>,
and others.
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.
END
}
show_help() {
cat <<END
evocheck is a script that verifies Evolix conventions on Linux (Debian) 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
}
detect_os() {
# OS detection
DEBIAN_RELEASE=""
LSB_RELEASE_BIN=$(command -v lsb_release)
if [ -e /etc/debian_version ]; then
DEBIAN_MAIN_VERSION=$(cut -d "." -f 1 < /etc/debian_version)
if [ "${DEBIAN_MAIN_VERSION}" -ne "8" ]; then
echo "Debian ${DEBIAN_MAIN_VERSION} is incompatible with this version of evocheck." >&2
echo "This version is built for Debian 8 only." >&2
exit
fi
DEBIAN_RELEASE="jessie"
fi
}
is_pack_web(){
test -e /usr/share/scripts/web-add.sh || test -e /usr/share/scripts/evoadmin/web-add.sh
}
is_pack_samba(){
test -e /usr/share/scripts/add.pl
}
is_installed(){
for pkg in "$@"; do
dpkg -l "$pkg" 2> /dev/null | grep -q -E '^(i|h)i' || return 1
done
}
# logging
failed() {
check_name=$1
shift
check_comments=$*
RC=1
if [ "${QUIET}" != 1 ]; then
if [ -n "${check_comments}" ] && [ "${VERBOSE}" = 1 ]; then
printf "%s FAILED! %s\n" "${check_name}" "${check_comments}" >> "${main_output_file}"
else
printf "%s FAILED!\n" "${check_name}" >> "${main_output_file}"
fi
fi
}
# check functions
check_lsbrelease(){
if [ -x "${LSB_RELEASE_BIN}" ]; then
## only the major version matters
lhs=$(${LSB_RELEASE_BIN} --release --short | cut -d "." -f 1)
rhs=$(cut -d "." -f 1 < /etc/debian_version)
test "$lhs" = "$rhs" || failed "IS_LSBRELEASE" "release is not consistent between lsb_release (${lhs}) and /etc/debian_version (${rhs})"
else
failed "IS_LSBRELEASE" "lsb_release is missing or not executable"
fi
}
# Verifying check_mailq in Nagios NRPE config file. (Option "-M postfix" need to be set if the MTA is Postfix)
check_nrpepostfix() {
if is_installed postfix; then
{ test -e /etc/nagios/nrpe.cfg \
&& grep -qr "^command.*check_mailq -M postfix" /etc/nagios/nrpe.*;
} || failed "IS_NRPEPOSTFIX" "NRPE \"check_mailq\" for postfix is missing"
fi
}
# Check if mod-security config file is present
check_customsudoers() {
grep -E -qr "umask=0077" /etc/sudoers* || failed "IS_CUSTOMSUDOERS" "missing umask=0077 in sudoers file"
}
check_vartmpfs() {
FINDMNT_BIN=$(command -v findmnt)
if [ -x "${FINDMNT_BIN}" ]; then
${FINDMNT_BIN} /var/tmp --type tmpfs --noheadings > /dev/null || failed "IS_VARTMPFS" "/var/tmp is not a tmpfs"
else
df /var/tmp | grep -q tmpfs || failed "IS_VARTMPFS" "/var/tmp is not a tmpfs"
fi
}
check_serveurbase() {
is_installed serveur-base || failed "IS_SERVEURBASE" "serveur-base package is not installed"
}
check_logrotateconf() {
test -e /etc/logrotate.d/zsyslog || failed "IS_LOGROTATECONF" "missing zsyslog in logrotate.d"
}
check_syslogconf() {
grep -q "^# Syslog for Pack Evolix serveur" /etc/*syslog.conf \
|| failed "IS_SYSLOGCONF" "syslog evolix config file missing"
}
check_debiansecurity() {
# Look for enabled "Debian-Security" sources from the "Debian" origin
apt-cache policy | grep "\bl=Debian-Security\b" | grep "\bo=Debian\b" | grep --quiet "\bc=main\b"
test $? -eq 0 || failed "IS_DEBIANSECURITY" "missing Debian-Security repository"
}
check_aptitude() {
test -e /usr/bin/aptitude && failed "IS_APTITUDE" "aptitude may not be installed on Debian >=8"
}
check_aptgetbak() {
test -e /usr/bin/apt-get.bak && failed "IS_APTGETBAK" "prohibit the installation of apt-get.bak with dpkg-divert(1)"
}
check_usrro() {
grep /usr /etc/fstab | grep -qE "\bro\b" || failed "IS_USRRO" "missing ro directive on fstab for /usr"
}
check_tmpnoexec() {
FINDMNT_BIN=$(command -v findmnt)
if [ -x "${FINDMNT_BIN}" ]; then
options=$(${FINDMNT_BIN} --noheadings --first-only --output OPTIONS /tmp)
echo "${options}" | grep -qE "\bnoexec\b" || failed "IS_TMPNOEXEC" "/tmp is not mounted with 'noexec'"
else
mount | grep "on /tmp" | grep -qE "\bnoexec\b" || failed "IS_TMPNOEXEC" "/tmp is not mounted with 'noexec' (WARNING: findmnt(8) is not found)"
fi
}
check_mountfstab() {
# Test if lsblk available, if not skip this test...
LSBLK_BIN=$(command -v lsblk)
if test -x "${LSBLK_BIN}"; then
for mountPoint in $(${LSBLK_BIN} -o MOUNTPOINT -l -n | grep '/'); do
grep -Eq "$mountPoint\W" /etc/fstab \
|| failed "IS_MOUNT_FSTAB" "partition(s) detected mounted but no presence in fstab"
done
fi
}
check_listchangesconf() {
if [ -e "/etc/apt/listchanges.conf" ]; then
lines=$(grep -cE "(which=both|confirm=1)" /etc/apt/listchanges.conf)
if [ "$lines" != 2 ]; then
failed "IS_LISTCHANGESCONF" "apt-listchanges config is incorrect"
fi
else
failed "IS_LISTCHANGESCONF" "apt-listchanges config is missing"
fi
}
check_customcrontab() {
found_lines=$(grep -c -E "^(17 \*|25 6|47 6|52 6)" /etc/crontab)
test "$found_lines" = 4 && failed "IS_CUSTOMCRONTAB" "missing custom field in crontab"
}
check_sshallowusers() {
grep -E -qir "(AllowUsers|AllowGroups)" /etc/ssh/sshd_config /etc/ssh/sshd_config.d \
|| failed "IS_SSHALLOWUSERS" "missing AllowUsers or AllowGroups directive in sshd_config"
}
check_diskperf() {
perfFile="/root/disk-perf.txt"
test -e $perfFile || failed "IS_DISKPERF" "missing ${perfFile}"
}
check_tmoutprofile() {
grep -sq "TMOUT=" /etc/profile /etc/profile.d/evolinux.sh || failed "IS_TMOUTPROFILE" "TMOUT is not set"
}
check_alert5boot() {
if [ -n "$(find /etc/rc2.d/ -name 'S*alert5')" ]; then
grep -q "^date" /etc/rc2.d/S*alert5 || failed "IS_ALERT5BOOT" "boot mail is not sent by alert5 init script"
elif [ -n "$(find /etc/init.d/ -name 'alert5')" ]; then
grep -q "^date" /etc/init.d/alert5 || failed "IS_ALERT5BOOT" "boot mail is not sent by alert5 int script"
else
failed "IS_ALERT5BOOT" "alert5 init script is missing"
fi
}
check_alert5minifw() {
if [ -n "$(find /etc/rc2.d/ -name 'S*alert5')" ]; then
grep -q "^/etc/init.d/minifirewall" /etc/rc2.d/S*alert5 \
|| failed "IS_ALERT5MINIFW" "Minifirewall is not started by alert5 init script"
elif [ -n "$(find /etc/init.d/ -name 'alert5')" ]; then
grep -q "^/etc/init.d/minifirewall" /etc/init.d/alert5 \
|| failed "IS_ALERT5MINIFW" "Minifirewall is not started by alert5 init script"
else
failed "IS_ALERT5MINIFW" "alert5 init script is missing"
fi
}
check_minifw() {
/sbin/iptables -L -n | grep -q -E "^ACCEPT\s*all\s*--\s*31\.170\.8\.4\s*0\.0\.0\.0/0\s*$" \
|| failed "IS_MINIFW" "minifirewall seems not started"
}
check_nrpeperms() {
if [ -d /etc/nagios ]; then
nagiosDir="/etc/nagios"
actual=$(stat --format "%a" $nagiosDir)
expected="750"
test "$expected" = "$actual" || failed "IS_NRPEPERMS" "${nagiosDir} must be ${expected}"
fi
}
check_minifwperms() {
if [ -f "/etc/default/minifirewall" ]; then
actual=$(stat --format "%a" "/etc/default/minifirewall")
expected="600"
test "$expected" = "$actual" || failed "IS_MINIFWPERMS" "/etc/default/minifirewall must be ${expected}"
fi
}
check_nrpedisks() {
NRPEDISKS=$(grep command.check_disk /etc/nagios/nrpe.cfg | grep "^command.check_disk[0-9]" | sed -e "s/^command.check_disk\([0-9]\+\).*/\1/" | sort -n | tail -1)
DFDISKS=$(df -Pl | grep -c -E -v "(^Filesystem|/lib/init/rw|/dev/shm|udev|rpc_pipefs)")
test "$NRPEDISKS" = "$DFDISKS" || failed "IS_NRPEDISKS" "there must be $DFDISKS check_disk in nrpe.cfg"
}
check_nrpepid() {
{ test -e /etc/nagios/nrpe.cfg \
&& grep -q "^pid_file=/var/run/nagios/nrpe.pid" /etc/nagios/nrpe.cfg;
} || failed "IS_NRPEPID" "missing or wrong pid_file directive in nrpe.cfg"
}
check_grsecprocs() {
if uname -a | grep -q grsec; then
{ grep -q "^command.check_total_procs..sudo" /etc/nagios/nrpe.cfg \
&& grep -A1 "^\[processes\]" /etc/munin/plugin-conf.d/munin-node | grep -q "^user root";
} || failed "IS_GRSECPROCS" "missing munin's plugin processes directive for grsec"
fi
}
check_apachemunin() {
if test -e /etc/apache2/apache2.conf; then
pattern="/server-status-[[:alnum:]]{4,}"
{ grep -r -q -s -E "^env.url.*${pattern}" /etc/munin/plugin-conf.d \
&& { grep -q -s -E "${pattern}" /etc/apache2/apache2.conf \
|| grep -q -s -E "${pattern}" /etc/apache2/mods-enabled/status.conf;
};
} || failed "IS_APACHEMUNIN" "server status is not properly configured"
fi
}
# Verification mytop + Munin si MySQL
check_mysqlutils() {
MYSQL_ADMIN=${MYSQL_ADMIN:-mysqladmin}
if is_installed mysql-server; then
# You can configure MYSQL_ADMIN in evocheck.cf
if ! grep -qs "^user *= *${MYSQL_ADMIN}" /root/.my.cnf; then
failed "IS_MYSQLUTILS" "${MYSQL_ADMIN} missing in /root/.my.cnf"
fi
if ! test -x /usr/bin/mytop; then
if ! test -x /usr/local/bin/mytop; then
failed "IS_MYSQLUTILS" "mytop binary missing"
fi
fi
if ! grep -qs '^user *=' /root/.mytop; then
failed "IS_MYSQLUTILS" "credentials missing in /root/.mytop"
fi
fi
}
# Verification de la configuration du raid soft (mdadm)
check_raidsoft() {
if test -e /proc/mdstat && grep -q md /proc/mdstat; then
{ grep -q "^AUTOCHECK=true" /etc/default/mdadm \
&& grep -q "^START_DAEMON=true" /etc/default/mdadm \
&& grep -qv "^MAILADDR ___MAIL___" /etc/mdadm/mdadm.conf;
} || failed "IS_RAIDSOFT" "missing or wrong config for mdadm"
fi
}
# Verification du LogFormat de AWStats
check_awstatslogformat() {
if is_installed apache2 awstats; then
awstatsFile="/etc/awstats/awstats.conf.local"
grep -qE '^LogFormat=1' $awstatsFile \
|| failed "IS_AWSTATSLOGFORMAT" "missing or wrong LogFormat directive in $awstatsFile"
fi
}
# Verification de la présence de la config logrotate pour Munin
check_muninlogrotate() {
{ test -e /etc/logrotate.d/munin-node \
&& test -e /etc/logrotate.d/munin;
} || failed "IS_MUNINLOGROTATE" "missing lorotate file for munin"
}
# Verification de l'activation de Squid dans le cas d'un pack mail
check_squid() {
squidconffile="/etc/squid*/squid.conf"
if is_pack_web && (is_installed squid || is_installed squid3); then
host=$(hostname -i)
# shellcheck disable=SC2086
http_port=$(grep -E "^http_port\s+[0-9]+" $squidconffile | awk '{ print $2 }')
{ grep -qE "^[^#]*iptables -t nat -A OUTPUT -p tcp --dport 80 -m owner --uid-owner proxy -j ACCEPT" "/etc/default/minifirewall" \
&& grep -qE "^[^#]*iptables -t nat -A OUTPUT -p tcp --dport 80 -d $host -j ACCEPT" "/etc/default/minifirewall" \
&& grep -qE "^[^#]*iptables -t nat -A OUTPUT -p tcp --dport 80 -d 127.0.0.(1|0/8) -j ACCEPT" "/etc/default/minifirewall" \
&& grep -qE "^[^#]*iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port.* $http_port" "/etc/default/minifirewall";
} || grep -qE "^PROXY='?on'?" "/etc/default/minifirewall" \
|| failed "IS_SQUID" "missing squid rules in minifirewall"
fi
}
check_evomaintenance_fw() {
if [ -f "/etc/default/minifirewall" ]; then
hook_db=$(grep -E '^\s*HOOK_DB' /etc/evomaintenance.cf | tr -d ' ' | cut -d= -f2)
rulesNumber=$(grep -c "/sbin/iptables -A INPUT -p tcp --sport 5432 --dport 1024:65535 -s .* -m state --state ESTABLISHED,RELATED -j ACCEPT" "/etc/default/minifirewall")
if [ "$hook_db" = "1" ] && [ "$rulesNumber" -lt 2 ]; then
failed "IS_EVOMAINTENANCE_FW" "HOOK_DB is enabled but missing evomaintenance rules in minifirewall"
fi
fi
}
# Verification de la conf et de l'activation de mod-deflate
check_moddeflate() {
f=/etc/apache2/mods-enabled/deflate.conf
if is_installed apache2.2; then
{ test -e $f && grep -q "AddOutputFilterByType DEFLATE text/html text/plain text/xml" $f \
&& grep -q "AddOutputFilterByType DEFLATE text/css" $f \
&& grep -q "AddOutputFilterByType DEFLATE application/x-javascript application/javascript" $f;
} || failed "IS_MODDEFLATE" "missing AddOutputFilterByType directive for apache mod deflate"
fi
}
# Verification de la conf log2mail
check_log2mailrunning() {
if is_pack_web && is_installed log2mail; then
pgrep log2mail >/dev/null || failed "IS_LOG2MAILRUNNING" "log2mail is not running"
fi
}
check_log2mailapache() {
conf=/etc/log2mail/config/default
if is_pack_web && is_installed log2mail; then
grep -s -q "^file = /var/log/apache2/error.log" $conf \
|| failed "IS_LOG2MAILAPACHE" "missing log2mail directive for apache"
fi
}
check_log2mailmysql() {
if is_pack_web && is_installed log2mail; then
grep -s -q "^file = /var/log/syslog" /etc/log2mail/config/{default,mysql,mysql.conf} \
|| failed "IS_LOG2MAILMYSQL" "missing log2mail directive for mysql"
fi
}
check_log2mailsquid() {
if is_pack_web && is_installed log2mail; then
grep -s -q "^file = /var/log/squid.*/access.log" /etc/log2mail/config/* \
|| failed "IS_LOG2MAILSQUID" "missing log2mail directive for squid"
fi
}
# Verification si bind est chroote
check_bindchroot() {
if is_installed bind9; then
if netstat -utpln | grep "/named" | grep :53 | grep -qvE "(127.0.0.1|::1)"; then
if grep -q '^OPTIONS=".*-t' /etc/default/bind9 && grep -q '^OPTIONS=".*-u' /etc/default/bind9; then
md5_original=$(md5sum /usr/sbin/named | cut -f 1 -d ' ')
md5_chrooted=$(md5sum /var/chroot-bind/usr/sbin/named | cut -f 1 -d ' ')
if [ "$md5_original" != "$md5_chrooted" ]; then
failed "IS_BINDCHROOT" "the chrooted bind binary is different than the original binary"
fi
else
failed "IS_BINDCHROOT" "bind process is not chrooted"
fi
fi
fi
}
# /etc/network/interfaces should be present, we don't manage systemd-network yet
check_network_interfaces() {
if ! test -f /etc/network/interfaces; then
IS_AUTOIF=0
IS_INTERFACESGW=0
failed "IS_NETWORK_INTERFACES" "systemd network configuration is not supported yet"
fi
}
# Verify if all if are in auto
check_autoif() {
interfaces=$(/sbin/ifconfig -s | tail -n +2 | grep -E -v "^(lo|vnet|docker|veth|tun|tap|macvtap|vrrp)" | cut -d " " -f 1 |tr "\n" " ")
for interface in $interfaces; do
if grep -Rq "^iface $interface" /etc/network/interfaces* && ! grep -Rq "^auto $interface" /etc/network/interfaces*; then
failed "IS_AUTOIF" "Network interface \`${interface}' is statically defined but not set to auto"
test "${VERBOSE}" = 1 || break
fi
done
}
# Network conf verification
check_interfacesgw() {
number=$(grep -Ec "^[^#]*gateway [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" /etc/network/interfaces)
test "$number" -gt 1 && failed "IS_INTERFACESGW" "there is more than 1 IPv4 gateway"
number=$(grep -Ec "^[^#]*gateway [0-9a-fA-F]+:" /etc/network/interfaces)
test "$number" -gt 1 && failed "IS_INTERFACESGW" "there is more than 1 IPv6 gateway"
}
# Verification de la mise en place d'evobackup
check_evobackup() {
evobackup_found=$(find /etc/cron* -name '*evobackup*' | wc -l)
test "$evobackup_found" -gt 0 || failed "IS_EVOBACKUP" "missing evobackup cron"
}
# Vérification de l'exclusion des montages (NFS) dans les sauvegardes
check_evobackup_exclude_mount() {
excludes_file=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.evobackup_exclude_mount.XXXXX")
files_to_cleanup="${files_to_cleanup} ${excludes_file}"
# shellcheck disable=SC2044
for evobackup_file in $(find /etc/cron* -name '*evobackup*' | grep -v -E ".disabled$"); do
# if the file seems to be a backup script, with an Rsync invocation
if grep -q "^\s*rsync" "${evobackup_file}"; then
# If rsync is not limited by "one-file-system"
# then we verify that every mount is excluded
if ! grep -q -- "^\s*--one-file-system" "${evobackup_file}"; then
grep -- "--exclude " "${evobackup_file}" | grep -E -o "\"[^\"]+\"" | tr -d '"' > "${excludes_file}"
not_excluded=$(findmnt --type nfs,nfs4,fuse.sshfs, -o target --noheadings | 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
fi
fi
done
}
# Verification de la presence du userlogrotate
check_userlogrotate() {
if is_pack_web; then
test -x /etc/cron.weekly/userlogrotate || failed "IS_USERLOGROTATE" "missing userlogrotate cron"
fi
}
# Verification de la syntaxe de la conf d'Apache
check_apachectl() {
if is_installed apache2; then
/usr/sbin/apache2ctl configtest 2>&1 | grep -q "^Syntax OK$" \
|| failed "IS_APACHECTL" "apache errors detected, run a configtest"
fi
}
# Check if there is regular files in Apache sites-enabled.
check_apachesymlink() {
if is_installed apache2; then
apacheFind=$(find /etc/apache2/sites-enabled ! -type l -type f -print)
nbApacheFind=$(wc -m <<< "$apacheFind")
if [[ $nbApacheFind -gt 1 ]]; then
if [[ $VERBOSE == 1 ]]; then
while read -r line; do
failed "IS_APACHESYMLINK" "Not a symlink: $line"
done <<< "$apacheFind"
else
failed "IS_APACHESYMLINK"
fi
fi
fi
}
# Check if there is real IP addresses in Allow/Deny directives (no trailing space, inline comments or so).
check_apacheipinallow() {
# Note: Replace "exit 1" by "print" in Perl code to debug it.
if is_installed apache2; then
grep -IrE "^[^#] *(Allow|Deny) from" /etc/apache2/ \
| grep -iv "from all" \
| grep -iv "env=" \
| perl -ne 'exit 1 unless (/from( [\da-f:.\/]+)+$/i)' \
|| failed "IS_APACHEIPINALLOW" "bad (Allow|Deny) directives in apache"
fi
}
# Check if default Apache configuration file for munin is absent (or empty or commented).
check_muninapacheconf() {
muninconf="/etc/apache2/conf-available/munin.conf"
if is_installed apache2; then
test -e $muninconf && grep -vEq "^( |\t)*#" "$muninconf" \
&& failed "IS_MUNINAPACHECONF" "default munin configuration may be commented or disabled"
fi
}
# Check if default Apache configuration file for phpMyAdmin is absent (or empty or commented).
check_phpmyadminapacheconf() {
phpmyadminconf0="/etc/apache2/conf-available/phpmyadmin.conf"
phpmyadminconf1="/etc/apache2/conf-enabled/phpmyadmin.conf"
if is_installed apache2; then
test -e $phpmyadminconf0 && grep -vEq "^( |\t)*#" "$phpmyadminconf0" \
&& failed "IS_PHPMYADMINAPACHECONF" "default phpmyadmin configuration ($phpmyadminconf0) may be commented or disabled"
test -e $phpmyadminconf1 && grep -vEq "^( |\t)*#" "$phpmyadminconf1" \
&& failed "IS_PHPMYADMINAPACHECONF" "default phpmyadmin configuration ($phpmyadminconf1) may be commented or disabled"
fi
}
# Verification si le système doit redémarrer suite màj kernel.
check_kerneluptodate() {
if is_installed linux-image*; then
# shellcheck disable=SC2012
kernel_installed_at=$(date -d "$(ls --full-time -lcrt /boot | tail -n1 | awk '{print $6}')" +%s)
last_reboot_at=$(($(date +%s) - $(cut -f1 -d '.' /proc/uptime)))
if [ "$kernel_installed_at" -gt "$last_reboot_at" ]; then
failed "IS_KERNELUPTODATE" "machine is running an outdated kernel, reboot advised"
fi
fi
}
# Check if the server is running for more than a year.
check_uptime() {
if is_installed linux-image*; then
limit=$(date -d "now - 2 year" +%s)
last_reboot_at=$(($(date +%s) - $(cut -f1 -d '.' /proc/uptime)))
if [ "$limit" -gt "$last_reboot_at" ]; then
failed "IS_UPTIME" "machine has an uptime of more than 2 years, reboot on new kernel advised"
fi
fi
}
# Check if munin-node running and RRD files are up to date.
check_muninrunning() {
if ! pgrep munin-node >/dev/null; then
failed "IS_MUNINRUNNING" "Munin is not running"
elif [ -d "/var/lib/munin/" ] && [ -d "/var/cache/munin/" ]; then
limit=$(date +"%s" -d "now - 10 minutes")
if [ -n "$(find /var/lib/munin/ -name '*load-g.rrd')" ]; then
updated_at=$(stat -c "%Y" /var/lib/munin/*/*load-g.rrd |sort |tail -1)
[ "$limit" -gt "$updated_at" ] && failed "IS_MUNINRUNNING" "Munin load RRD has not been updated in the last 10 minutes"
else
failed "IS_MUNINRUNNING" "Munin is not installed properly (load RRD not found)"
fi
if [ -n "$(find /var/cache/munin/www/ -name 'load-day.png')" ]; then
updated_at=$(stat -c "%Y" /var/cache/munin/www/*/*/load-day.png |sort |tail -1)
grep -sq "^graph_strategy cron" /etc/munin/munin.conf && [ "$limit" -gt "$updated_at" ] && failed "IS_MUNINRUNNING" "Munin load PNG has not been updated in the last 10 minutes"
else
failed "IS_MUNINRUNNING" "Munin is not installed properly (load PNG not found)"
fi
else
failed "IS_MUNINRUNNING" "Munin is not installed properly (main directories are missing)"
fi
}
# Check if files in /home/backup/ are up-to-date
check_backupuptodate() {
backup_dir="/home/backup"
if [ -d "${backup_dir}" ]; then
if [ -n "$(ls -A ${backup_dir})" ]; then
find "${backup_dir}" -maxdepth 1 -type f | while read -r file; do
limit=$(date +"%s" -d "now - 2 day")
updated_at=$(stat -c "%Y" "$file")
if [ "$limit" -gt "$updated_at" ]; then
failed "IS_BACKUPUPTODATE" "$file has not been backed up"
test "${VERBOSE}" = 1 || break;
fi
done
else
failed "IS_BACKUPUPTODATE" "${backup_dir}/ is empty"
fi
else
failed "IS_BACKUPUPTODATE" "${backup_dir}/ is missing"
fi
}
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 if /etc/.git/ has read/write permissions for root only.
check_gitperms() {
GIT_DIR="/etc/.git"
if test -d $GIT_DIR; then
expected="700"
actual=$(stat -c "%a" $GIT_DIR)
[ "$expected" = "$actual" ] || failed "IS_GITPERMS" "$GIT_DIR must be $expected"
fi
}
# Check if no package has been upgraded since $limit.
check_notupgraded() {
last_upgrade=0
upgraded=false
for log in /var/log/dpkg.log*; do
if zgrep -qsm1 upgrade "$log"; then
# There is at least one upgrade
upgraded=true
break
fi
done
if $upgraded; then
last_upgrade=$(date +%s -d "$(zgrep -h upgrade /var/log/dpkg.log* | sort -n | tail -1 | cut -f1 -d ' ')")
fi
if grep -qs '^mailto="listupgrade-todo@' /etc/evolinux/listupgrade.cnf \
|| grep -qs -E '^[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[^\*]' /etc/cron.d/listupgrade; then
# Manual upgrade process
limit=$(date +%s -d "now - 180 days")
else
# Regular process
limit=$(date +%s -d "now - 90 days")
fi
install_date=0
if [ -d /var/log/installer ]; then
install_date=$(stat -c %Z /var/log/installer)
fi
# Check install_date if the system never received an upgrade
if [ "$last_upgrade" -eq 0 ]; then
[ "$install_date" -lt "$limit" ] && failed "IS_NOTUPGRADED" "The system has never been updated"
else
[ "$last_upgrade" -lt "$limit" ] && failed "IS_NOTUPGRADED" "The system hasn't been updated for too long"
fi
}
# Check if reserved blocks for root is at least 5% on every mounted partitions.
check_tune2fs_m5() {
min=5
parts=$(grep -E "ext(3|4)" /proc/mounts | cut -d ' ' -f1 | tr -s '\n' ' ')
FINDMNT_BIN=$(command -v findmnt)
for part in $parts; do
blockCount=$(dumpe2fs -h "$part" 2>/dev/null | grep -e "Block count:" | grep -Eo "[0-9]+")
# If buggy partition, skip it.
if [ -z "$blockCount" ]; then
continue
fi
reservedBlockCount=$(dumpe2fs -h "$part" 2>/dev/null | grep -e "Reserved block count:" | grep -Eo "[0-9]+")
# Use awk to have a rounded percentage
# python is slow, bash is unable and bc rounds weirdly
percentage=$(awk "BEGIN { pc=100*${reservedBlockCount}/${blockCount}; i=int(pc); print (pc-i<0.5)?i:i+1 }")
if [ "$percentage" -lt "${min}" ]; then
if [ -x "${FINDMNT_BIN}" ]; then
mount=$(${FINDMNT_BIN} --noheadings --first-only --output TARGET "${part}")
else
mount="unknown mount point"
fi
failed "IS_TUNE2FS_M5" "Partition ${part} (${mount}) has less than ${min}% reserved blocks (${percentage}%)"
fi
done
}
check_broadcomfirmware() {
LSPCI_BIN=$(command -v lspci)
if [ -x "${LSPCI_BIN}" ]; then
if ${LSPCI_BIN} | grep -q 'NetXtreme II'; then
{ is_installed firmware-bnx2 \
&& grep -q "^deb http://mirror.evolix.org/debian.* non-free" /etc/apt/sources.list;
} || failed "IS_BROADCOMFIRMWARE" "missing non-free repository"
fi
else
failed "IS_BROADCOMFIRMWARE" "lspci not found in ${PATH}"
fi
}
check_hardwareraidtool() {
LSPCI_BIN=$(command -v lspci)
if [ -x "${LSPCI_BIN}" ]; then
if ${LSPCI_BIN} | grep -q 'MegaRAID'; then
# shellcheck disable=SC2015
is_installed megacli && { is_installed megaclisas-status || is_installed megaraidsas-status; } \
|| failed "IS_HARDWARERAIDTOOL" "Mega tools not found"
fi
if ${LSPCI_BIN} | grep -q 'Hewlett-Packard Company Smart Array'; then
is_installed cciss-vol-status || failed "IS_HARDWARERAIDTOOL" "cciss-vol-status not installed"
fi
else
failed "IS_HARDWARERAIDTOOL" "lspci not found in ${PATH}"
fi
}
check_listupgrade() {
test -f /etc/cron.d/listupgrade \
|| failed "IS_LISTUPGRADE" "missing listupgrade cron"
test -x /usr/share/scripts/listupgrade.sh \
|| failed "IS_LISTUPGRADE" "missing listupgrade script or not executable"
}
check_sql_backup() {
if (is_installed "mysql-server" || is_installed "mariadb-server"); then
# You could change the default path in /etc/evocheck.cf
SQL_BACKUP_PATH=${SQL_BACKUP_PATH:-"/home/backup/mysql.bak.gz"}
for backup_path in ${SQL_BACKUP_PATH}; do
if [ ! -f "${backup_path}" ]; then
failed "IS_SQL_BACKUP" "MySQL dump is missing (${backup_path})"
test "${VERBOSE}" = 1 || break
fi
done
fi
}
check_postgres_backup() {
if is_installed "postgresql-9*" || is_installed "postgresql-1*"; then
# If you use something like barman, you should disable this check
# You could change the default path in /etc/evocheck.cf
POSTGRES_BACKUP_PATH=${POSTGRES_BACKUP_PATH:-"/home/backup/pg.dump.bak*"}
for backup_path in ${POSTGRES_BACKUP_PATH}; do
if [ ! -f "${backup_path}" ]; then
failed "IS_POSTGRES_BACKUP" "PostgreSQL dump is missing (${backup_path})"
test "${VERBOSE}" = 1 || break
fi
done
fi
}
check_mongo_backup() {
if is_installed "mongodb-org-server"; then
# You could change the default path in /etc/evocheck.cf
MONGO_BACKUP_PATH=${MONGO_BACKUP_PATH:-"/home/backup/mongodump"}
if [ -d "$MONGO_BACKUP_PATH" ]; then
for file in "${MONGO_BACKUP_PATH}"/*/*.{json,bson}*; do
# Skip indexes file.
if ! [[ "$file" =~ indexes ]]; then
limit=$(date +"%s" -d "now - 2 day")
updated_at=$(stat -c "%Y" "$file")
if [ -f "$file" ] && [ "$limit" -gt "$updated_at" ]; then
failed "IS_MONGO_BACKUP" "MongoDB hasn't been dumped for more than 2 days"
break
fi
fi
done
else
failed "IS_MONGO_BACKUP" "MongoDB dump directory is missing (${MONGO_BACKUP_PATH})"
fi
fi
}
check_ldap_backup() {
if is_installed slapd; then
# You could change the default path in /etc/evocheck.cf
LDAP_BACKUP_PATH=${LDAP_BACKUP_PATH:-"/home/backup/ldap.bak"}
test -f "$LDAP_BACKUP_PATH" || failed "IS_LDAP_BACKUP" "LDAP dump is missing (${LDAP_BACKUP_PATH})"
fi
}
check_redis_backup() {
if is_installed redis-server; then
# You could change the default path in /etc/evocheck.cf
# REDIS_BACKUP_PATH may contain space-separated paths, example:
# REDIS_BACKUP_PATH='/home/backup/redis-instance1/dump.rdb /home/backup/redis-instance2/dump.rdb'
REDIS_BACKUP_PATH=${REDIS_BACKUP_PATH:-"/home/backup/redis/dump.rdb"}
for file in ${REDIS_BACKUP_PATH}; do
test -f "${file}" || failed "IS_REDIS_BACKUP" "Redis dump is missing (${file})"
done
fi
}
check_elastic_backup() {
if is_installed elasticsearch; then
# You could change the default path in /etc/evocheck.cf
ELASTIC_BACKUP_PATH=${ELASTIC_BACKUP_PATH:-"/home/backup-elasticsearch"}
test -d "$ELASTIC_BACKUP_PATH" || failed "IS_ELASTIC_BACKUP" "Elastic snapshot is missing (${ELASTIC_BACKUP_PATH})"
fi
}
check_duplicate_fs_label() {
# Do it only if thereis blkid binary
BLKID_BIN=$(command -v blkid)
if [ -n "$BLKID_BIN" ]; then
tmpFile=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.duplicate_fs_label.XXXXX")
files_to_cleanup="${files_to_cleanup} ${tmpFile}"
parts=$($BLKID_BIN -c /dev/null | grep -ve raid_member -e EFI_SYSPART | grep -Eo ' LABEL=".*"' | cut -d'"' -f2)
for part in $parts; do
echo "$part" >> "$tmpFile"
done
tmpOutput=$(sort < "$tmpFile" | uniq -d)
# If there is no duplicate, uniq will have no output
# So, if $tmpOutput is not null, there is a duplicate
if [ -n "$tmpOutput" ]; then
# shellcheck disable=SC2086
labels=$(echo -n $tmpOutput | tr '\n' ' ')
failed "IS_DUPLICATE_FS_LABEL" "Duplicate labels: $labels"
fi
else
failed "IS_DUPLICATE_FS_LABEL" "blkid not found in ${PATH}"
fi
}
check_evolix_user() {
grep -q -E "^evolix:" /etc/passwd \
&& failed "IS_EVOLIX_USER" "evolix user should be deleted, used only for install"
}
check_evoacme_cron() {
if [ -f "/usr/local/sbin/evoacme" ]; then
# Old cron file, should be deleted
test -f /etc/cron.daily/certbot && failed "IS_EVOACME_CRON" "certbot cron is incompatible with evoacme"
# evoacme cron file should be present
test -f /etc/cron.daily/evoacme || failed "IS_EVOACME_CRON" "evoacme cron is missing"
fi
}
check_evoacme_livelinks() {
EVOACME_BIN=$(command -v evoacme)
if [ -x "$EVOACME_BIN" ]; then
# Sometimes evoacme is installed but no certificates has been generated
numberOfLinks=$(find /etc/letsencrypt/ -type l | wc -l)
if [ "$numberOfLinks" -gt 0 ]; then
for live in /etc/letsencrypt/*/live; do
actualLink=$(readlink -f "$live")
actualVersion=$(basename "$actualLink")
certDir=$(dirname "$live")
certName=$(basename "$certDir")
# shellcheck disable=SC2012
lastCertDir=$(ls -ds "${certDir}"/[0-9]* | tail -1)
lastVersion=$(basename "$lastCertDir")
if [[ "$lastVersion" != "$actualVersion" ]]; then
failed "IS_EVOACME_LIVELINKS" "Certificate \`$certName' hasn't been updated"
test "${VERBOSE}" = 1 || break
fi
done
fi
fi
}
check_apache_confenabled() {
# Starting from Jessie and Apache 2.4, /etc/apache2/conf.d/
# must be replaced by conf-available/ and config files symlinked
# to conf-enabled/
if [ -f /etc/apache2/apache2.conf ]; then
test -d /etc/apache2/conf.d/ \
&& failed "IS_APACHE_CONFENABLED" "apache's conf.d directory must not exists"
grep -q 'Include conf.d' /etc/apache2/apache2.conf \
&& failed "IS_APACHE_CONFENABLED" "apache2.conf must not Include conf.d"
fi
}
check_meltdown_spectre() {
# For Jessie this is quite complicated to verify and we need to use kernel config file
if grep -q "BOOT_IMAGE=" /proc/cmdline; then
kernelPath=$(grep -Eo 'BOOT_IMAGE=[^ ]+' /proc/cmdline | cut -d= -f2)
kernelVer=${kernelPath##*/vmlinuz-}
kernelConfig="config-${kernelVer}"
# Sometimes autodetection of kernel config file fail, so we test if the file really exists.
if [ -f "/boot/${kernelConfig}" ]; then
grep -Eq '^CONFIG_PAGE_TABLE_ISOLATION=y' "/boot/$kernelConfig" \
|| failed "IS_MELTDOWN_SPECTRE" \
"PAGE_TABLE_ISOLATION must be enabled in kernel, outdated kernel?"
grep -Eq '^CONFIG_RETPOLINE=y' "/boot/$kernelConfig" \
|| failed "IS_MELTDOWN_SPECTRE" \
"RETPOLINE must be enabled in kernel, outdated kernel?"
fi
fi
}
check_old_home_dir() {
homeDir=${homeDir:-/home}
for dir in "$homeDir"/*; do
statResult=$(stat -c "%n has owner %u resolved as %U" "$dir" \
| grep -Eve '.bak' -e '\.[0-9]{2}-[0-9]{2}-[0-9]{4}' \
| grep "UNKNOWN")
# There is at least one dir matching
if [[ -n "$statResult" ]]; then
failed "IS_OLD_HOME_DIR" "$statResult"
test "${VERBOSE}" = 1 || break
fi
done
}
check_tmp_1777() {
actual=$(stat --format "%a" /tmp)
expected="1777"
test "$expected" = "$actual" || failed "IS_TMP_1777" "/tmp must be $expected"
}
check_root_0700() {
actual=$(stat --format "%a" /root)
expected="700"
test "$expected" = "$actual" || failed "IS_ROOT_0700" "/root must be $expected"
}
check_usrsharescripts() {
actual=$(stat --format "%a" /usr/share/scripts)
expected="700"
test "$expected" = "$actual" || failed "IS_USRSHARESCRIPTS" "/usr/share/scripts must be $expected"
}
check_sshpermitrootno() {
sshd_args="-C addr=,user=,host=,laddr=,lport=0"
# shellcheck disable=SC2086
if ! (sshd -T ${sshd_args} 2> /dev/null | grep -qi 'permitrootlogin no'); then
failed "IS_SSHPERMITROOTNO" "PermitRoot should be set to no"
fi
}
check_evomaintenanceusers() {
if [ -f /etc/sudoers.d/evolinux ]; then
sudoers="/etc/sudoers.d/evolinux"
else
sudoers="/etc/sudoers"
fi
# combine users from User_Alias and sudo group
users=$({ grep "^User_Alias *ADMIN" $sudoers | cut -d= -f2 | tr -d " "; grep "^sudo" /etc/group | cut -d: -f 4; } | tr "," "\n" | sort -u)
for user in $users; do
user_home=$(getent passwd "$user" | cut -d: -f6)
if [ -n "$user_home" ] && [ -d "$user_home" ]; then
if ! grep -qs "^trap.*sudo.*evomaintenance.sh" "${user_home}"/.*profile; then
failed "IS_EVOMAINTENANCEUSERS" "${user} doesn't have an evomaintenance trap"
test "${VERBOSE}" = 1 || break
fi
fi
done
}
check_evomaintenanceconf() {
f=/etc/evomaintenance.cf
if [ -e "$f" ]; then
perms=$(stat -c "%a" $f)
test "$perms" = "600" || failed "IS_EVOMAINTENANCECONF" "Wrong permissions on \`$f' ($perms instead of 600)"
{ 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"
} || failed "IS_EVOMAINTENANCECONF" "evomaintenance is not correctly configured"
else
failed "IS_EVOMAINTENANCECONF" "Configuration file \`$f' is missing"
fi
}
check_privatekeyworldreadable() {
# a simple globbing fails if directory is empty
if [ -n "$(ls -A /etc/ssl/private/)" ]; then
for f in /etc/ssl/private/*; do
perms=$(stat -L -c "%a" "$f")
if [ "${perms: -1}" != 0 ]; then
failed "IS_PRIVKEYWOLRDREADABLE" "$f is world-readable"
test "${VERBOSE}" = 1 || break
fi
done
fi
}
check_evobackup_incs() {
if is_installed bkctld; then
bkctld_cron_file=${bkctld_cron_file:-/etc/cron.d/bkctld}
if [ -f "${bkctld_cron_file}" ]; then
root_crontab=$(grep -v "^#" "${bkctld_cron_file}")
echo "${root_crontab}" | grep -q "bkctld inc" || failed "IS_EVOBACKUP_INCS" "\`bkctld inc' is missing in ${bkctld_cron_file}"
echo "${root_crontab}" | grep -qE "(check-incs.sh|bkctld check-incs)" || failed "IS_EVOBACKUP_INCS" "\`check-incs.sh' is missing in ${bkctld_cron_file}"
else
failed "IS_EVOBACKUP_INCS" "Crontab \`${bkctld_cron_file}' is missing"
fi
fi
}
check_osprober() {
if is_installed os-prober qemu-kvm; then
failed "IS_OSPROBER" \
"Removal of os-prober package is recommended as it can cause serious issue on KVM server"
fi
}
check_jessie_backports() {
jessieBackports=$(grep -hs "jessie-backports" /etc/apt/sources.list /etc/apt/sources.list.d/*)
if test -n "$jessieBackports"; then
if ! grep -q "archive.debian.org" <<< "$jessieBackports"; then
failed "IS_JESSIE_BACKPORTS" "You must use deb http://archive.debian.org/debian/ jessie-backports main"
fi
fi
}
check_apt_valid_until() {
aptvalidFile="/etc/apt/apt.conf.d/99no-check-valid-until"
aptvalidText="Acquire::Check-Valid-Until no;"
if grep -qs "archive.debian.org" /etc/apt/sources.list /etc/apt/sources.list.d/*; then
if ! grep -qs "$aptvalidText" /etc/apt/apt.conf.d/*; then
failed "IS_APT_VALID_UNTIL" \
"As you use archive.mirror.org you need ${aptvalidFile}: ${aptvalidText}"
fi
fi
}
check_chrooted_binary_uptodate() {
# list of processes to check
process_list="sshd"
for process_name in ${process_list}; do
# what is the binary path?
original_bin=$(command -v "${process_name}")
for pid in $(pgrep ${process_name}); do
process_bin=$(realpath "/proc/${pid}/exe")
# Is the process chrooted?
real_root=$(realpath "/proc/${pid}/root")
if [ "${real_root}" != "/" ]; then
chrooted_md5=$(md5sum "${process_bin}" | cut -f 1 -d ' ')
original_md5=$(md5sum "${original_bin}" | cut -f 1 -d ' ')
# compare md5 checksums
if [ "$original_md5" != "$chrooted_md5" ]; then
failed "IS_CHROOTED_BINARY_UPTODATE" "${process_bin} (${pid}) is different than ${original_bin}."
test "${VERBOSE}" = 1 || break
fi
fi
done
done
}
check_nginx_letsencrypt_uptodate() {
if [ -d /etc/nginx ]; then
snippets=$(find /etc/nginx -type f -name "letsencrypt.conf")
if [ -n "${snippets}" ]; then
while read -r snippet; do
if ! grep -qE "^\s*alias\s+/.+/\.well-known/acme-challenge" "${snippet}"; then
failed "IS_NGINX_LETSENCRYPT_UPTODATE" "Nginx snippet ${snippet} is not compatible with Nginx on Debian 8."
fi
done <<< "${snippets}"
fi
fi
}
check_lxc_container_resolv_conf() {
if is_installed lxc; then
container_list=$(lxc-ls)
current_resolvers=$(grep nameserver /etc/resolv.conf | sed 's/nameserver//g' )
for container in $container_list; do
if [ -f "/var/lib/lxc/${container}/rootfs/etc/resolv.conf" ]; then
while read -r resolver; do
if ! grep -qE "^nameserver\s+${resolver}" "/var/lib/lxc/${container}/rootfs/etc/resolv.conf"; then
failed "IS_LXC_CONTAINER_RESOLV_CONF" "resolv.conf miss-match beween host and container : missing nameserver ${resolver} in container ${container} resolv.conf"
fi
done <<< "${current_resolvers}"
else
failed "IS_LXC_CONTAINER_RESOLV_CONF" "resolv.conf missing in container ${container}"
fi
done
fi
}
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-${DEBIAN_RELEASE}"
# fetch timeout, in seconds
timeout=10
if command -v curl > /dev/null; then
curl --max-time ${timeout} --fail --silent --output "${versions_file}" "${versions_url}"
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_CHECK_VERSIONS" "failed to find curl, wget or GET"
fi
test "$?" -eq 0 || failed "IS_CHECK_VERSIONS" "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" ;;
listupgrade) command -v "evolistupgrade.sh" ;;
old-kernel-autoremoval) command -v "old-kernel-autoremoval.sh" ;;
mysql-queries-killer) command -v "mysql-queries-killer.sh" ;;
minifirewall) echo "/etc/init.d/minifirewall" ;;
## 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:-}