Merge pull request 'Release 22.12' (#165) from unstable into stable
Reviewed-on: #165
This commit is contained in:
commit
e1e4f39778
57
CHANGELOG.md
57
CHANGELOG.md
|
@ -20,6 +20,60 @@ The **patch** part changes is incremented if multiple releases happen the same m
|
|||
|
||||
### Security
|
||||
|
||||
## [22.12] 2022-12-14
|
||||
|
||||
### Added
|
||||
|
||||
* all: add signed-by option for additional APT sources
|
||||
* all: preliminary work to support Debian 12
|
||||
* all: use proper keyrings directory for APT version
|
||||
* evolinux-base: replace regular kernel by cloud kernel on virtual servers
|
||||
* lxc-php: set php-fpm umask to `007`
|
||||
* nagios-nrpe: `check_ceph_*`
|
||||
* nagios-nrpe: `check_haproxy_stats` supports DRAIN status
|
||||
* packweb-apache: enable `log_forensic` module
|
||||
* rabbitmq: add link in default page
|
||||
* varnish: create special tmp directory for syntax validation
|
||||
|
||||
### Changed
|
||||
|
||||
* certbot: auto-detect HAPEE version in renewal hook
|
||||
* evocheck: install script according to Debian version
|
||||
* evolinux-base: `utils.yml` can be excluded
|
||||
* evolinux-todo: execute tasks only for Debian distribution (because this task is a dependency for others roles used on different distributions)
|
||||
* evolinux-user: add sudoers privilege for check `php_fpm81`
|
||||
* evomaintenance: allow missing API endpoint if APi is disabled
|
||||
* java: use default JRE package when version is not specified
|
||||
* keepalived: change exit code (_warning_ if running but not on expected state ; _critical_ if not running)
|
||||
* listupgrade: better detection for PostgreSQL
|
||||
* listupgrade: sort/uniq of packages/services lists in email template
|
||||
* lxc-solr: detect the real partition options
|
||||
* lxc-solr: download URL according to Solr Version
|
||||
* lxc-solr: set homedir and port at install
|
||||
* minifirewall: whitelist deb.freexian.com
|
||||
* openvpn: shellpki upstream release 22.12.2
|
||||
* openvpn: specifies that the mail for expirations is for OpenVPN
|
||||
* packweb-apache: manual dependencies resolution
|
||||
* redis: some values should be quoted
|
||||
* redis: variable to disable transparent hugepage (default: do nothing)
|
||||
* squid: whitelist `deb.freexian.com`
|
||||
* varnish: better package facts usage with check mode and tags
|
||||
* varnish: systemd override depends on Varnish version instead of Debian version
|
||||
|
||||
### Fixed
|
||||
|
||||
* evolinux-user: Fix sudoers privilege for check `php_fpm80`
|
||||
* nagios-nrpe: Fix check opendkim for recent change in listening port
|
||||
* openvpn: Fix mode of shellpki script
|
||||
* proftpd: Fix format of public key files controlled by Ansible
|
||||
* proftpd: Fix mode of public key directory and files (they have to be accessible by `proftpd:nobody`)
|
||||
* varnish: fix missing state, that blocked the task
|
||||
|
||||
### Removed
|
||||
|
||||
* openvpn: Deleted the task fixing the CRL rights since it has been fixed in upstream
|
||||
|
||||
|
||||
## [22.09] 2022-09-19
|
||||
|
||||
### Added
|
||||
|
@ -151,7 +205,7 @@ The **patch** part changes is incremented if multiple releases happen the same m
|
|||
* minifirewall: tail template follows symlinks
|
||||
* mysql: add "set crypt_use_gpgme=no" Mutt option, for mysqltuner
|
||||
|
||||
### Fixed
|
||||
### Fixed
|
||||
|
||||
* Role `postfix`: Add missing `localhost.localdomain localhost` to `mydestination` variable which caused undelivered of some local mails.
|
||||
|
||||
|
@ -443,6 +497,7 @@ The **patch** part changes is incremented if multiple releases happen the same m
|
|||
|
||||
### Added
|
||||
|
||||
* bookworm-detect: transitional role to help dealing with unreleased bookworm version
|
||||
* dovecot: Update munin plugin & configure it
|
||||
* dovecot: vmail uid/gid are configurable
|
||||
* evoacme: variable to disable Debian version check (default: False)
|
||||
|
|
|
@ -25,3 +25,5 @@ apt_check_hold_cron_hour: "*/4"
|
|||
apt_check_hold_cron_weekday: "*"
|
||||
apt_check_hold_cron_day: "*"
|
||||
apt_check_hold_cron_month: "*"
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -19,7 +19,7 @@
|
|||
- name: Add Evolix GPG key
|
||||
copy:
|
||||
src: reg.asc
|
||||
dest: /etc/apt/trusted.gpg.d/reg.asc
|
||||
dest: "{{ apt_keyring_dir }}/reg.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
|
|
5
apt/templates/bookworm_basics.list.j2
Normal file
5
apt/templates/bookworm_basics.list.j2
Normal file
|
@ -0,0 +1,5 @@
|
|||
# {{ ansible_managed }}
|
||||
|
||||
deb http://mirror.evolix.org/debian bookworm {{ apt_basics_components | mandatory }}
|
||||
deb http://mirror.evolix.org/debian/ bookworm-updates {{ apt_basics_components | mandatory }}
|
||||
deb http://security.debian.org/debian-security bookworm-security {{ apt_basics_components | mandatory }}
|
|
@ -1,3 +1,7 @@
|
|||
# {{ ansible_managed }}
|
||||
|
||||
deb http://pub.evolix.net/ {{ ansible_distribution_release }}/
|
||||
{% if ansible_distribution_release == "bookworm" %}
|
||||
deb [signed-by={{ apt_keyring_dir }}/reg.asc] http://pub.evolix.net/ bullseye/
|
||||
{% else %}
|
||||
deb [signed-by={{ apt_keyring_dir }}/reg.asc] http://pub.evolix.net/ {{ ansible_distribution_release }}/
|
||||
{% endif %}
|
11
bookworm-detect/tasks/main.yml
Normal file
11
bookworm-detect/tasks/main.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
|
||||
- debug:
|
||||
var: ansible_lsb
|
||||
|
||||
# Force facts until Debian 12 is released because Ansible is dumb
|
||||
- set_fact:
|
||||
ansible_distribution_major_version: 12
|
||||
ansible_distribution: "Debian"
|
||||
ansible_distribution_release: "bookworm"
|
||||
when: "ansible_lsb.codename == 'bookworm'"
|
|
@ -10,7 +10,17 @@ debug() {
|
|||
fi
|
||||
}
|
||||
daemon_found_and_running() {
|
||||
test -n "$(pidof hapee-lb)" && test -n "${hapee_bin}"
|
||||
readonly hapee_main_pid=$(ps -u root u | grep hapee-lb | grep -v grep | awk '{print $2}')
|
||||
if [ -n "${hapee_main_pid}" ] && [ -d "/proc/${hapee_main_pid}" ] ; then
|
||||
readonly hapee_bin=$(readlink "/proc/${hapee_main_pid}/exe")
|
||||
readonly hapee_config_file=$(cat "/proc/${hapee_main_pid}/cmdline" | tr "\0" " " | grep --only-matching --extended-regexp -- "-f \S+" | awk '{print $2}')
|
||||
readonly hapee_pid_file=$(cat "/proc/${hapee_main_pid}/cmdline" | tr "\0" " " | grep --only-matching --extended-regexp -- "-p \S+" | awk '{print $2}')
|
||||
readonly hapee_service_name="$(basename -s .pid "${hapee_pid_file}").service"
|
||||
|
||||
kill -0 "${hapee_main_pid}" && test -n "${hapee_bin}" && test -f "${hapee_config_file}" && systemctl -q is-active "${hapee_service_name}"
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
found_renewed_lineage() {
|
||||
test -f "${RENEWED_LINEAGE}/fullchain.pem" && test -f "${RENEWED_LINEAGE}/privkey.pem"
|
||||
|
@ -40,12 +50,6 @@ detect_hapee_cert_dir() {
|
|||
if [ -n "${config_cert_dir}" ]; then
|
||||
debug "Cert directory is configured with ${config_cert_dir}"
|
||||
echo "${config_cert_dir}"
|
||||
elif [ -d "/etc/haproxy/ssl" ]; then
|
||||
debug "No configured cert directory found, but /etc/haproxy/ssl exists"
|
||||
echo "/etc/haproxy/ssl"
|
||||
elif [ -d "/etc/ssl/haproxy" ]; then
|
||||
debug "No configured cert directory found, but /etc/ssl/haproxy exists"
|
||||
echo "/etc/ssl/haproxy"
|
||||
else
|
||||
error "Cert directory not found."
|
||||
fi
|
||||
|
@ -56,7 +60,6 @@ main() {
|
|||
fi
|
||||
|
||||
if daemon_found_and_running; then
|
||||
readonly hapee_config_file="/etc/hapee-2.4/hapee-lb.cfg"
|
||||
readonly hapee_cert_dir=$(detect_hapee_cert_dir)
|
||||
|
||||
if found_renewed_lineage; then
|
||||
|
@ -72,7 +75,7 @@ main() {
|
|||
|
||||
if config_check; then
|
||||
debug "HAPEE detected... reloading"
|
||||
systemctl reload hapee-2.4-lb.service
|
||||
systemctl reload "${hapee_service_name}"
|
||||
else
|
||||
error "HAPEE config is broken, you must fix it !"
|
||||
fi
|
||||
|
@ -88,6 +91,4 @@ readonly PROGNAME=$(basename "$0")
|
|||
readonly VERBOSE=${VERBOSE:-"0"}
|
||||
readonly QUIET=${QUIET:-"0"}
|
||||
|
||||
readonly hapee_bin="/opt/hapee-2.4/sbin/hapee-lb"
|
||||
|
||||
main
|
||||
|
|
|
@ -28,10 +28,6 @@ main() {
|
|||
if [ -z "${RENEWED_LINEAGE}" ]; then
|
||||
error "Missing RENEWED_LINEAGE environment variable (usually provided by certbot)."
|
||||
fi
|
||||
if [ -z "${servers}" ]; then
|
||||
debug "Empty server list, skip."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if found_renewed_lineage; then
|
||||
RENEWED_DOMAINS=${RENEWED_DOMAINS:-$(domain_from_cert)}
|
||||
|
|
|
@ -28,3 +28,5 @@ docker_tls_ca_key: ca/ca-key.pem
|
|||
docker_tls_cert: server/cert.pem
|
||||
docker_tls_key: server/key.pem
|
||||
docker_tls_csr: server/server.csr
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -19,7 +19,7 @@
|
|||
- name: Add Docker's official GPG key
|
||||
copy:
|
||||
src: docker-debian.asc
|
||||
dest: /etc/apt/trusted.gpg.d/docker-debian.asc
|
||||
dest: "{{ apt_keyring_dir }}/docker-debian.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
|
@ -27,10 +27,16 @@
|
|||
|
||||
- name: Add Docker repository
|
||||
apt_repository:
|
||||
repo: 'deb [arch=amd64] https://download.docker.com/linux/debian {{ ansible_distribution_release }} stable'
|
||||
repo: 'deb [signed-by={{ apt_keyring_dir }}/docker-debian.asc] https://download.docker.com/linux/debian {{ ansible_distribution_release }} stable'
|
||||
state: present
|
||||
filename: docker.list
|
||||
|
||||
- name: Drop unsigned Docker repository
|
||||
apt_repository:
|
||||
repo: 'deb https://download.docker.com/linux/debian {{ ansible_distribution_release }} stable'
|
||||
state: absent
|
||||
filename: docker.list
|
||||
|
||||
- name: Install Docker
|
||||
apt:
|
||||
name:
|
||||
|
|
|
@ -29,3 +29,5 @@ elasticsearch_plugin_head_clone_dir: "{{ elasticsearch_plugin_head_home }}/www"
|
|||
elasticsearch_plugin_head_tmp_dir: "{{ elasticsearch_plugin_head_home }}/tmp"
|
||||
|
||||
elasticsearch_additional_scripts_dir: /usr/share/scripts
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -29,7 +29,7 @@
|
|||
- name: Elastic GPG key is installed
|
||||
copy:
|
||||
src: elastic.asc
|
||||
dest: /etc/apt/trusted.gpg.d/elastic.asc
|
||||
dest: "{{ apt_keyring_dir }}/elastic.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
|
@ -40,7 +40,7 @@
|
|||
|
||||
- name: Elastic sources list is available
|
||||
apt_repository:
|
||||
repo: "deb https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
repo: "deb [signed-by={{ apt_keyring_dir }}/elastic.asc] https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
filename: elastic
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
@ -48,6 +48,16 @@
|
|||
- elasticsearch
|
||||
- packages
|
||||
|
||||
- name: Unsigned Elastic sources list is not available
|
||||
apt_repository:
|
||||
repo: "deb https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
filename: elastic
|
||||
state: absent
|
||||
update_cache: yes
|
||||
tags:
|
||||
- elasticsearch
|
||||
- packages
|
||||
|
||||
- name: Elasticsearch is installed
|
||||
apt:
|
||||
name: elasticsearch
|
||||
|
|
1307
evocheck/files/evocheck.jessie.sh
Executable file
1307
evocheck/files/evocheck.jessie.sh
Executable file
|
@ -0,0 +1,1307 @@
|
|||
#!/bin/bash
|
||||
|
||||
# EvoCheck
|
||||
# Script to verify compliance of a Linux (Debian) server
|
||||
# powered by Evolix
|
||||
|
||||
VERSION="22.11"
|
||||
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:-}
|
||||
|
||||
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
|
||||
# ;;
|
||||
|
||||
add-vm)
|
||||
grep '^VERSION=' "${command}" | head -1 | cut -d '=' -f 2
|
||||
;;
|
||||
minifirewall)
|
||||
${command} version | head -1 | cut -d ' ' -f 3
|
||||
;;
|
||||
## Let's try the --version flag before falling back to grep for the constant
|
||||
kvmstats)
|
||||
if ${command} --version > /dev/null 2> /dev/null; then
|
||||
${command} --version 2> /dev/null | head -1 | cut -d ' ' -f 3
|
||||
else
|
||||
grep '^VERSION=' "${command}" | head -1 | cut -d '=' -f 2
|
||||
fi
|
||||
;;
|
||||
|
||||
## 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
|
||||
# shellcheck disable=SC2086
|
||||
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_CHECK_VERSIONS" "failed to lookup actual version of ${program}"
|
||||
elif dpkg --compare-versions "${actual_version}" lt "${expected_version}"; then
|
||||
failed "IS_CHECK_VERSIONS" "${program} version ${actual_version} is older than expected version ${expected_version}"
|
||||
elif dpkg --compare-versions "${actual_version}" gt "${expected_version}"; then
|
||||
failed "IS_CHECK_VERSIONS" "${program} version ${actual_version} is newer than expected version ${expected_version}, you should update your index."
|
||||
else
|
||||
: # Version check OK
|
||||
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 --tmpdir="${TMPDIR:-/tmp}" "evocheck.versions.XXXXX")
|
||||
files_to_cleanup="${files_to_cleanup} ${versions_file}"
|
||||
|
||||
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_CHECK_VERSIONS" "failed to lookup expected version for ${program}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
# Default return code : 0 = no error
|
||||
RC=0
|
||||
# Detect operating system name, version and release
|
||||
detect_os
|
||||
|
||||
main_output_file=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.main.XXXXX")
|
||||
files_to_cleanup="${files_to_cleanup} ${main_output_file}"
|
||||
|
||||
test "${IS_TMP_1777:=1}" = 1 && check_tmp_1777
|
||||
test "${IS_ROOT_0700:=1}" = 1 && check_root_0700
|
||||
test "${IS_USRSHARESCRIPTS:=1}" = 1 && check_usrsharescripts
|
||||
test "${IS_SSHPERMITROOTNO:=1}" = 1 && check_sshpermitrootno
|
||||
test "${IS_EVOMAINTENANCEUSERS:=1}" = 1 && check_evomaintenanceusers
|
||||
# Verification de la configuration d'evomaintenance
|
||||
test "${IS_EVOMAINTENANCECONF:=1}" = 1 && check_evomaintenanceconf
|
||||
test "${IS_PRIVKEYWOLRDREADABLE:=1}" = 1 && check_privatekeyworldreadable
|
||||
|
||||
test "${IS_LSBRELEASE:=1}" = 1 && check_lsbrelease
|
||||
test "${IS_NRPEPOSTFIX:=1}" = 1 && check_nrpepostfix
|
||||
test "${IS_CUSTOMSUDOERS:=1}" = 1 && check_customsudoers
|
||||
test "${IS_VARTMPFS:=1}" = 1 && check_vartmpfs
|
||||
test "${IS_SERVEURBASE:=1}" = 1 && check_serveurbase
|
||||
test "${IS_LOGROTATECONF:=1}" = 1 && check_logrotateconf
|
||||
test "${IS_SYSLOGCONF:=1}" = 1 && check_syslogconf
|
||||
test "${IS_DEBIANSECURITY:=1}" = 1 && check_debiansecurity
|
||||
test "${IS_APTITUDE:=1}" = 1 && check_aptitude
|
||||
test "${IS_APTGETBAK:=1}" = 1 && check_aptgetbak
|
||||
test "${IS_USRRO:=1}" = 1 && check_usrro
|
||||
test "${IS_TMPNOEXEC:=1}" = 1 && check_tmpnoexec
|
||||
test "${IS_MOUNT_FSTAB:=1}" = 1 && check_mountfstab
|
||||
test "${IS_LISTCHANGESCONF:=1}" = 1 && check_listchangesconf
|
||||
test "${IS_CUSTOMCRONTAB:=1}" = 1 && check_customcrontab
|
||||
test "${IS_SSHALLOWUSERS:=1}" = 1 && check_sshallowusers
|
||||
test "${IS_DISKPERF:=0}" = 1 && check_diskperf
|
||||
test "${IS_TMOUTPROFILE:=1}" = 1 && check_tmoutprofile
|
||||
test "${IS_ALERT5BOOT:=1}" = 1 && check_alert5boot
|
||||
test "${IS_ALERT5MINIFW:=1}" = 1 && check_alert5minifw
|
||||
test "${IS_ALERT5MINIFW:=1}" = 1 && test "${IS_MINIFW:=1}" = 1 && check_minifw
|
||||
test "${IS_NRPEPERMS:=1}" = 1 && check_nrpeperms
|
||||
test "${IS_MINIFWPERMS:=1}" = 1 && check_minifwperms
|
||||
test "${IS_NRPEDISKS:=0}" = 1 && check_nrpedisks
|
||||
test "${IS_NRPEPID:=1}" = 1 && check_nrpepid
|
||||
test "${IS_GRSECPROCS:=1}" = 1 && check_grsecprocs
|
||||
test "${IS_APACHEMUNIN:=1}" = 1 && check_apachemunin
|
||||
test "${IS_MYSQLUTILS:=1}" = 1 && check_mysqlutils
|
||||
test "${IS_RAIDSOFT:=1}" = 1 && check_raidsoft
|
||||
test "${IS_AWSTATSLOGFORMAT:=1}" = 1 && check_awstatslogformat
|
||||
test "${IS_MUNINLOGROTATE:=1}" = 1 && check_muninlogrotate
|
||||
test "${IS_SQUID:=1}" = 1 && check_squid
|
||||
test "${IS_EVOMAINTENANCE_FW:=1}" = 1 && check_evomaintenance_fw
|
||||
test "${IS_MODDEFLATE:=1}" = 1 && check_moddeflate
|
||||
test "${IS_LOG2MAILRUNNING:=1}" = 1 && check_log2mailrunning
|
||||
test "${IS_LOG2MAILAPACHE:=1}" = 1 && check_log2mailapache
|
||||
test "${IS_LOG2MAILMYSQL:=1}" = 1 && check_log2mailmysql
|
||||
test "${IS_LOG2MAILSQUID:=1}" = 1 && check_log2mailsquid
|
||||
test "${IS_BINDCHROOT:=1}" = 1 && check_bindchroot
|
||||
test "${IS_NETWORK_INTERFACES:=1}" = 1 && check_network_interfaces
|
||||
test "${IS_AUTOIF:=1}" = 1 && check_autoif
|
||||
test "${IS_INTERFACESGW:=1}" = 1 && check_interfacesgw
|
||||
test "${IS_EVOBACKUP:=1}" = 1 && check_evobackup
|
||||
test "${IS_EVOBACKUP_EXCLUDE_MOUNT:=1}" = 1 && check_evobackup_exclude_mount
|
||||
test "${IS_USERLOGROTATE:=1}" = 1 && check_userlogrotate
|
||||
test "${IS_APACHECTL:=1}" = 1 && check_apachectl
|
||||
test "${IS_APACHESYMLINK:=1}" = 1 && check_apachesymlink
|
||||
test "${IS_APACHEIPINALLOW:=1}" = 1 && check_apacheipinallow
|
||||
test "${IS_MUNINAPACHECONF:=1}" = 1 && check_muninapacheconf
|
||||
test "${IS_PHPMYADMINAPACHECONF:=1}" = 1 && check_phpmyadminapacheconf
|
||||
test "${IS_KERNELUPTODATE:=1}" = 1 && check_kerneluptodate
|
||||
test "${IS_UPTIME:=1}" = 1 && check_uptime
|
||||
test "${IS_MUNINRUNNING:=1}" = 1 && check_muninrunning
|
||||
test "${IS_BACKUPUPTODATE:=1}" = 1 && check_backupuptodate
|
||||
test "${IS_ETCGIT:=1}" = 1 && check_etcgit
|
||||
test "${IS_GITPERMS:=1}" = 1 && check_gitperms
|
||||
test "${IS_NOTUPGRADED:=1}" = 1 && check_notupgraded
|
||||
test "${IS_TUNE2FS_M5:=1}" = 1 && check_tune2fs_m5
|
||||
test "${IS_BROADCOMFIRMWARE:=1}" = 1 && check_broadcomfirmware
|
||||
test "${IS_HARDWARERAIDTOOL:=1}" = 1 && check_hardwareraidtool
|
||||
test "${IS_LISTUPGRADE:=1}" = 1 && check_listupgrade
|
||||
test "${IS_SQL_BACKUP:=1}" = 1 && check_sql_backup
|
||||
test "${IS_POSTGRES_BACKUP:=1}" = 1 && check_postgres_backup
|
||||
test "${IS_MONGO_BACKUP:=1}" = 1 && check_mongo_backup
|
||||
test "${IS_LDAP_BACKUP:=1}" = 1 && check_ldap_backup
|
||||
test "${IS_REDIS_BACKUP:=1}" = 1 && check_redis_backup
|
||||
test "${IS_ELASTIC_BACKUP:=1}" = 1 && check_elastic_backup
|
||||
test "${IS_DUPLICATE_FS_LABEL:=1}" = 1 && check_duplicate_fs_label
|
||||
test "${IS_EVOLIX_USER:=1}" = 1 && check_evolix_user
|
||||
test "${IS_EVOACME_CRON:=1}" = 1 && check_evoacme_cron
|
||||
test "${IS_EVOACME_LIVELINKS:=1}" = 1 && check_evoacme_livelinks
|
||||
test "${IS_APACHE_CONFENABLED:=1}" = 1 && check_apache_confenabled
|
||||
test "${IS_MELTDOWN_SPECTRE:=1}" = 1 && check_meltdown_spectre
|
||||
test "${IS_OLD_HOME_DIR:=0}" = 1 && check_old_home_dir
|
||||
test "${IS_EVOBACKUP_INCS:=1}" = 1 && check_evobackup_incs
|
||||
test "${IS_OSPROBER:=1}" = 1 && check_osprober
|
||||
test "${IS_JESSIE_BACKPORTS:=1}" = 1 && check_jessie_backports
|
||||
test "${IS_APT_VALID_UNTIL:=1}" = 1 && check_apt_valid_until
|
||||
test "${IS_CHROOTED_BINARY_UPTODATE:=1}" = 1 && check_chrooted_binary_uptodate
|
||||
test "${IS_NGINX_LETSENCRYPT_UPTODATE:=1}" = 1 && check_nginx_letsencrypt_uptodate
|
||||
test "${IS_LXC_CONTAINER_RESOLV_CONF:=1}" = 1 && check_lxc_container_resolv_conf
|
||||
test "${IS_CHECK_VERSIONS:=1}" = 1 && check_versions
|
||||
|
||||
if [ -f "${main_output_file}" ]; then
|
||||
lines_found=$(wc -l < "${main_output_file}")
|
||||
# shellcheck disable=SC2086
|
||||
if [ ${lines_found} -gt 0 ]; then
|
||||
|
||||
cat "${main_output_file}" 2>&1
|
||||
fi
|
||||
fi
|
||||
|
||||
exit ${RC}
|
||||
}
|
||||
cleanup_temp_files() {
|
||||
# shellcheck disable=SC2086
|
||||
rm -f ${files_to_cleanup}
|
||||
}
|
||||
|
||||
PROGNAME=$(basename "$0")
|
||||
# shellcheck disable=SC2034
|
||||
readonly PROGNAME
|
||||
|
||||
# shellcheck disable=SC2124
|
||||
ARGS=$@
|
||||
readonly ARGS
|
||||
|
||||
# Disable LANG*
|
||||
export LANG=C
|
||||
export LANGUAGE=C
|
||||
|
||||
files_to_cleanup=""
|
||||
# shellcheck disable=SC2064
|
||||
trap cleanup_temp_files 0
|
||||
|
||||
# Source configuration file
|
||||
# shellcheck disable=SC1091
|
||||
test -f /etc/evocheck.cf && . /etc/evocheck.cf
|
||||
|
||||
# Parse options
|
||||
# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
|
||||
while :; do
|
||||
case $1 in
|
||||
-h|-\?|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
--version)
|
||||
show_version
|
||||
exit 0
|
||||
;;
|
||||
--cron)
|
||||
IS_KERNELUPTODATE=0
|
||||
IS_UPTIME=0
|
||||
IS_MELTDOWN_SPECTRE=0
|
||||
IS_CHECK_VERSIONS=0
|
||||
IS_NETWORKING_SERVICE=0
|
||||
;;
|
||||
-v|--verbose)
|
||||
VERBOSE=1
|
||||
;;
|
||||
-q|--quiet)
|
||||
QUIET=1
|
||||
VERBOSE=0
|
||||
;;
|
||||
--)
|
||||
# End of all options.
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-?*|[[:alnum:]]*)
|
||||
# ignore unknown options
|
||||
if [ "${QUIET}" != 1 ]; then
|
||||
printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# Default case: If no more options then break out of the loop.
|
||||
break
|
||||
;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
main ${ARGS}
|
|
@ -4,7 +4,7 @@
|
|||
# Script to verify compliance of a Linux (Debian) server
|
||||
# powered by Evolix
|
||||
|
||||
VERSION="22.09"
|
||||
VERSION="22.11"
|
||||
readonly VERSION
|
||||
|
||||
# base functions
|
||||
|
@ -52,16 +52,19 @@ detect_os() {
|
|||
LSB_RELEASE_BIN=$(command -v lsb_release)
|
||||
|
||||
if [ -e /etc/debian_version ]; then
|
||||
DEBIAN_VERSION=$(cut -d "." -f 1 < /etc/debian_version)
|
||||
DEBIAN_MAIN_VERSION=$(cut -d "." -f 1 < /etc/debian_version)
|
||||
|
||||
if [ "${DEBIAN_MAIN_VERSION}" -lt "9" ]; then
|
||||
echo "Debian ${DEBIAN_MAIN_VERSION} is incompatible with this version of evocheck." >&2
|
||||
echo "This version is built for Debian 9 and later." >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ -x "${LSB_RELEASE_BIN}" ]; then
|
||||
DEBIAN_RELEASE=$(${LSB_RELEASE_BIN} --codename --short)
|
||||
else
|
||||
case ${DEBIAN_VERSION} in
|
||||
5) DEBIAN_RELEASE="lenny";;
|
||||
6) DEBIAN_RELEASE="squeeze";;
|
||||
7) DEBIAN_RELEASE="wheezy";;
|
||||
8) DEBIAN_RELEASE="jessie";;
|
||||
9) DEBIAN_RELEASE="stretch";;
|
||||
case ${DEBIAN_MAIN_VERSION} in
|
||||
9) DEBIAN_RELEASE="stretch";;
|
||||
10) DEBIAN_RELEASE="buster";;
|
||||
11) DEBIAN_RELEASE="bullseye";;
|
||||
12) DEBIAN_RELEASE="bookworm";;
|
||||
|
@ -70,21 +73,6 @@ detect_os() {
|
|||
fi
|
||||
}
|
||||
|
||||
is_debian() {
|
||||
test -n "${DEBIAN_RELEASE}"
|
||||
}
|
||||
is_debian_lenny() {
|
||||
test "${DEBIAN_RELEASE}" = "lenny"
|
||||
}
|
||||
is_debian_squeeze() {
|
||||
test "${DEBIAN_RELEASE}" = "squeeze"
|
||||
}
|
||||
is_debian_wheezy() {
|
||||
test "${DEBIAN_RELEASE}" = "wheezy"
|
||||
}
|
||||
is_debian_jessie() {
|
||||
test "${DEBIAN_RELEASE}" = "jessie"
|
||||
}
|
||||
is_debian_stretch() {
|
||||
test "${DEBIAN_RELEASE}" = "stretch"
|
||||
}
|
||||
|
@ -97,12 +85,6 @@ is_debian_bullseye() {
|
|||
is_debian_bookworm() {
|
||||
test "${DEBIAN_RELEASE}" = "bookworm"
|
||||
}
|
||||
debian_release() {
|
||||
printf "%s" "${DEBIAN_RELEASE}"
|
||||
}
|
||||
debian_version() {
|
||||
printf "%s" "${DEBIAN_VERSION}"
|
||||
}
|
||||
|
||||
is_pack_web(){
|
||||
test -e /usr/share/scripts/web-add.sh || test -e /usr/share/scripts/evoadmin/web-add.sh
|
||||
|
@ -115,16 +97,6 @@ is_installed(){
|
|||
dpkg -l "$pkg" 2> /dev/null | grep -q -E '^(i|h)i' || return 1
|
||||
done
|
||||
}
|
||||
minifirewall_file() {
|
||||
case ${DEBIAN_RELEASE} in
|
||||
lenny) echo "/etc/firewall.rc" ;;
|
||||
squeeze) echo "/etc/firewall.rc" ;;
|
||||
wheezy) echo "/etc/firewall.rc" ;;
|
||||
jessie) echo "/etc/default/minifirewall" ;;
|
||||
stretch) echo "/etc/default/minifirewall" ;;
|
||||
*) echo "/etc/default/minifirewall" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# logging
|
||||
|
||||
|
@ -156,54 +128,18 @@ check_lsbrelease(){
|
|||
fi
|
||||
}
|
||||
check_dpkgwarning() {
|
||||
if is_debian_squeeze; then
|
||||
if [ "$IS_USRRO" = 1 ] || [ "$IS_TMPNOEXEC" = 1 ]; then
|
||||
count=$(grep -c -E -i "(Pre-Invoke ..echo Are you sure to have rw on|Post-Invoke ..echo Dont forget to mount -o remount)" /etc/apt/apt.conf)
|
||||
test "$count" = 2 || failed "IS_DPKGWARNING" "Pre/Post-Invoke are missing."
|
||||
fi
|
||||
elif is_debian_wheezy; then
|
||||
if [ "$IS_USRRO" = 1 ] || [ "$IS_TMPNOEXEC" = 1 ]; then
|
||||
test -e /etc/apt/apt.conf.d/80evolinux \
|
||||
|| failed "IS_DPKGWARNING" "/etc/apt/apt.conf.d/80evolinux is missing"
|
||||
test -e /etc/apt/apt.conf \
|
||||
&& failed "IS_DPKGWARNING" "/etc/apt/apt.conf is missing"
|
||||
fi
|
||||
elif is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
test -e /etc/apt/apt.conf.d/z-evolinux.conf \
|
||||
|| failed "IS_DPKGWARNING" "/etc/apt/apt.conf.d/z-evolinux.conf is missing"
|
||||
fi
|
||||
}
|
||||
check_umasksudoers(){
|
||||
if is_debian_squeeze; then
|
||||
grep -q "^Defaults.*umask=0077" /etc/sudoers \
|
||||
|| failed "IS_UMASKSUDOERS" "sudoers must set umask to 0077"
|
||||
fi
|
||||
test -e /etc/apt/apt.conf.d/z-evolinux.conf \
|
||||
|| failed "IS_DPKGWARNING" "/etc/apt/apt.conf.d/z-evolinux.conf is missing"
|
||||
}
|
||||
# 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
|
||||
if is_debian_squeeze; then
|
||||
grep -q "^command.*check_mailq -M postfix" /etc/nagios/nrpe.cfg \
|
||||
|| failed "IS_NRPEPOSTFIX" "NRPE \"check_mailq\" for postfix is missing"
|
||||
else
|
||||
{ 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
|
||||
{ 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_modsecurity() {
|
||||
if is_debian_squeeze; then
|
||||
if is_installed libapache-mod-security; then
|
||||
test -e /etc/apache2/conf.d/mod-security2.conf || failed "IS_MODSECURITY" "missing configuration file"
|
||||
fi
|
||||
elif is_debian_wheezy; then
|
||||
if is_installed libapache2-modsecurity; then
|
||||
test -e /etc/apache2/conf.d/mod-security2.conf || failed "IS_MODSECURITY" "missing configuration file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
check_customsudoers() {
|
||||
grep -E -qr "umask=0077" /etc/sudoers* || failed "IS_CUSTOMSUDOERS" "missing umask=0077 in sudoers file"
|
||||
}
|
||||
|
@ -226,46 +162,15 @@ check_syslogconf() {
|
|||
|| failed "IS_SYSLOGCONF" "syslog evolix config file missing"
|
||||
}
|
||||
check_debiansecurity() {
|
||||
if is_debian_bullseye; then
|
||||
# https://www.debian.org/releases/bullseye/amd64/release-notes/ch-information.html#security-archive
|
||||
# https://www.debian.org/security/
|
||||
pattern="^deb ?(\[.*\])? ?http://security\.debian\.org/debian-security/? bullseye-security main"
|
||||
elif is_debian_buster; then
|
||||
pattern="^deb ?(\[.*\])? ?http://security\.debian\.org/debian-security/? buster/updates main"
|
||||
elif is_debian_stretch; then
|
||||
pattern="^deb ?(\[.*\])? ?http://security\.debian\.org/debian-security/? stretch/updates main"
|
||||
else
|
||||
pattern="^deb.*security"
|
||||
fi
|
||||
|
||||
source_file="/etc/apt/sources.list"
|
||||
grep -qE "${pattern}" "${source_file}" || failed "IS_DEBIANSECURITY" "missing debian security repository"
|
||||
}
|
||||
check_aptitudeonly() {
|
||||
if is_debian_squeeze || is_debian_wheezy; then
|
||||
test -e /usr/bin/apt-get && failed "IS_APTITUDEONLY" \
|
||||
"only aptitude may be enabled on Debian <=7, apt-get should be disabled"
|
||||
fi
|
||||
# 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() {
|
||||
if is_debian_jessie || is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
test -e /usr/bin/aptitude && failed "IS_APTITUDE" "aptitude may not be installed on Debian >=8"
|
||||
fi
|
||||
test -e /usr/bin/aptitude && failed "IS_APTITUDE" "aptitude may not be installed on Debian >=8"
|
||||
}
|
||||
check_aptgetbak() {
|
||||
if is_debian_jessie || is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
test -e /usr/bin/apt-get.bak && failed "IS_APTGETBAK" "prohibit the installation of apt-get.bak with dpkg-divert(1)"
|
||||
fi
|
||||
}
|
||||
check_apticron() {
|
||||
status="OK"
|
||||
test -e /etc/cron.d/apticron || status="fail"
|
||||
test -e /etc/cron.daily/apticron && status="fail"
|
||||
test "$status" = "fail" || test -e /usr/bin/apt-get.bak || status="fail"
|
||||
|
||||
if is_debian_squeeze || is_debian_wheezy; then
|
||||
test "$status" = "fail" && failed "IS_APTICRON" "apticron must be in cron.d not cron.daily"
|
||||
fi
|
||||
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"
|
||||
|
@ -290,19 +195,8 @@ check_mountfstab() {
|
|||
fi
|
||||
}
|
||||
check_listchangesconf() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
if is_installed apt-listchanges; then
|
||||
failed "IS_LISTCHANGESCONF" "apt-listchanges must not be installed on Debian >=9"
|
||||
fi
|
||||
else
|
||||
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
|
||||
if is_installed apt-listchanges; then
|
||||
failed "IS_LISTCHANGESCONF" "apt-listchanges must not be installed on Debian >=9"
|
||||
fi
|
||||
}
|
||||
check_customcrontab() {
|
||||
|
@ -321,14 +215,7 @@ check_tmoutprofile() {
|
|||
grep -sq "TMOUT=" /etc/profile /etc/profile.d/evolinux.sh || failed "IS_TMOUTPROFILE" "TMOUT is not set"
|
||||
}
|
||||
check_alert5boot() {
|
||||
if is_debian_buster || is_debian_bullseye; then
|
||||
grep -qs "^date" /usr/share/scripts/alert5.sh || failed "IS_ALERT5BOOT" "boot mail is not sent by alert5 init script"
|
||||
if [ -f /etc/systemd/system/alert5.service ]; then
|
||||
systemctl is-enabled alert5.service -q || failed "IS_ALERT5BOOT" "alert5 unit is not enabled"
|
||||
else
|
||||
failed "IS_ALERT5BOOT" "alert5 unit file is missing"
|
||||
fi
|
||||
else
|
||||
if is_debian_stretch; then
|
||||
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
|
||||
|
@ -336,13 +223,17 @@ check_alert5boot() {
|
|||
else
|
||||
failed "IS_ALERT5BOOT" "alert5 init script is missing"
|
||||
fi
|
||||
else
|
||||
grep -qs "^date" /usr/share/scripts/alert5.sh || failed "IS_ALERT5BOOT" "boot mail is not sent by alert5 init script"
|
||||
if [ -f /etc/systemd/system/alert5.service ]; then
|
||||
systemctl is-enabled alert5.service -q || failed "IS_ALERT5BOOT" "alert5 unit is not enabled"
|
||||
else
|
||||
failed "IS_ALERT5BOOT" "alert5 unit file is missing"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
check_alert5minifw() {
|
||||
if is_debian_buster || is_debian_bullseye; then
|
||||
grep -qs "^/etc/init.d/minifirewall" /usr/share/scripts/alert5.sh \
|
||||
|| failed "IS_ALERT5MINIFW" "Minifirewall is not started by alert5 script or script is missing"
|
||||
else
|
||||
if is_debian_stretch; then
|
||||
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"
|
||||
|
@ -352,6 +243,9 @@ check_alert5minifw() {
|
|||
else
|
||||
failed "IS_ALERT5MINIFW" "alert5 init script is missing"
|
||||
fi
|
||||
else
|
||||
grep -qs "^/etc/init.d/minifirewall" /usr/share/scripts/alert5.sh \
|
||||
|| failed "IS_ALERT5MINIFW" "Minifirewall is not started by alert5 script or script is missing"
|
||||
fi
|
||||
}
|
||||
check_minifw() {
|
||||
|
@ -360,8 +254,8 @@ check_minifw() {
|
|||
}
|
||||
check_minifw_includes() {
|
||||
if is_debian_bullseye; then
|
||||
if grep -q -e '/sbin/iptables' -e '/sbin/ip6tables' "${MINIFW_FILE}"; then
|
||||
failed "IS_MINIFWINCLUDES" "minifirewall has direct iptables invocations in ${MINIFW_FILE} that should go in /etc/minifirewall.d/"
|
||||
if grep -q -e '/sbin/iptables' -e '/sbin/ip6tables' "/etc/default/minifirewall"; then
|
||||
failed "IS_MINIFWINCLUDES" "minifirewall has direct iptables invocations in /etc/default/minifirewall that should go in /etc/minifirewall.d/"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
@ -374,10 +268,10 @@ check_nrpeperms() {
|
|||
fi
|
||||
}
|
||||
check_minifwperms() {
|
||||
if [ -f "$MINIFW_FILE" ]; then
|
||||
actual=$(stat --format "%a" "$MINIFW_FILE")
|
||||
if [ -f "/etc/default/minifirewall" ]; then
|
||||
actual=$(stat --format "%a" "/etc/default/minifirewall")
|
||||
expected="600"
|
||||
test "$expected" = "$actual" || failed "IS_MINIFWPERMS" "${MINIFW_FILE} must be ${expected}"
|
||||
test "$expected" = "$actual" || failed "IS_MINIFWPERMS" "/etc/default/minifirewall must be ${expected}"
|
||||
fi
|
||||
}
|
||||
check_nrpedisks() {
|
||||
|
@ -390,7 +284,7 @@ check_nrpepid() {
|
|||
{ test -e /etc/nagios/nrpe.cfg \
|
||||
&& grep -q "^pid_file=/run/nagios/nrpe.pid" /etc/nagios/nrpe.cfg;
|
||||
} || failed "IS_NRPEPID" "missing or wrong pid_file directive in nrpe.cfg"
|
||||
elif ! is_debian_squeeze; then
|
||||
else
|
||||
{ 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"
|
||||
|
@ -405,20 +299,11 @@ check_grsecprocs() {
|
|||
}
|
||||
check_apachemunin() {
|
||||
if test -e /etc/apache2/apache2.conf; then
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
{ test -h /etc/apache2/mods-enabled/status.load \
|
||||
&& test -h /etc/munin/plugins/apache_accesses \
|
||||
&& test -h /etc/munin/plugins/apache_processes \
|
||||
&& test -h /etc/munin/plugins/apache_volume;
|
||||
} || failed "IS_APACHEMUNIN" "missing munin plugins for Apache"
|
||||
else
|
||||
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
|
||||
{ test -h /etc/apache2/mods-enabled/status.load \
|
||||
&& test -h /etc/munin/plugins/apache_accesses \
|
||||
&& test -h /etc/munin/plugins/apache_processes \
|
||||
&& test -h /etc/munin/plugins/apache_volume;
|
||||
} || failed "IS_APACHEMUNIN" "missing munin plugins for Apache"
|
||||
fi
|
||||
}
|
||||
# Verification mytop + Munin si MySQL
|
||||
|
@ -426,7 +311,7 @@ check_mysqlutils() {
|
|||
MYSQL_ADMIN=${MYSQL_ADMIN:-mysqladmin}
|
||||
if is_installed mysql-server; then
|
||||
# With Debian 11 and later, root can connect to MariaDB with the socket
|
||||
if is_debian_wheezy || is_debian_jessie || is_debian_stretch || is_debian_buster; then
|
||||
if is_debian_stretch || is_debian_buster; 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"
|
||||
|
@ -467,27 +352,23 @@ check_muninlogrotate() {
|
|||
}
|
||||
# Verification de l'activation de Squid dans le cas d'un pack mail
|
||||
check_squid() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
squidconffile="/etc/squid/evolinux-custom.conf"
|
||||
else
|
||||
squidconffile="/etc/squid*/squid.conf"
|
||||
fi
|
||||
squidconffile="/etc/squid/evolinux-custom.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" "$MINIFW_FILE" \
|
||||
&& grep -qE "^[^#]*iptables -t nat -A OUTPUT -p tcp --dport 80 -d $host -j ACCEPT" "$MINIFW_FILE" \
|
||||
&& grep -qE "^[^#]*iptables -t nat -A OUTPUT -p tcp --dport 80 -d 127.0.0.(1|0/8) -j ACCEPT" "$MINIFW_FILE" \
|
||||
&& grep -qE "^[^#]*iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port.* $http_port" "$MINIFW_FILE";
|
||||
} || grep -qE "^PROXY='?on'?" "$MINIFW_FILE" \
|
||||
{ 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 "$MINIFW_FILE" ]; then
|
||||
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" "$MINIFW_FILE")
|
||||
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
|
||||
|
@ -510,11 +391,7 @@ check_log2mailrunning() {
|
|||
fi
|
||||
}
|
||||
check_log2mailapache() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
conf=/etc/log2mail/config/apache
|
||||
else
|
||||
conf=/etc/log2mail/config/default
|
||||
fi
|
||||
conf=/etc/log2mail/config/Apache
|
||||
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"
|
||||
|
@ -548,17 +425,6 @@ check_bindchroot() {
|
|||
fi
|
||||
fi
|
||||
}
|
||||
# Verification de la présence du depot volatile
|
||||
check_repvolatile() {
|
||||
if is_debian_lenny; then
|
||||
grep -qE "^deb http://volatile.debian.org/debian-volatile" /etc/apt/sources.list \
|
||||
|| failed "IS_REPVOLATILE" "missing debian-volatile repository"
|
||||
fi
|
||||
if is_debian_squeeze; then
|
||||
grep -qE "^deb.*squeeze-updates" /etc/apt/sources.list \
|
||||
|| failed "IS_REPVOLATILE" "missing squeeze-updates repository"
|
||||
fi
|
||||
}
|
||||
# /etc/network/interfaces should be present, we don't manage systemd-network yet
|
||||
check_network_interfaces() {
|
||||
if ! test -f /etc/network/interfaces; then
|
||||
|
@ -569,11 +435,7 @@ check_network_interfaces() {
|
|||
}
|
||||
# Verify if all if are in auto
|
||||
check_autoif() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
interfaces=$(/sbin/ip address show up | grep "^[0-9]*:" | grep -E -v "(lo|vnet|docker|veth|tun|tap|macvtap|vrrp|lxcbr|wg)" | cut -d " " -f 2 | tr -d : | cut -d@ -f1 | tr "\n" " ")
|
||||
else
|
||||
interfaces=$(/sbin/ifconfig -s | tail -n +2 | grep -E -v "^(lo|vnet|docker|veth|tun|tap|macvtap|vrrp)" | cut -d " " -f 1 |tr "\n" " ")
|
||||
fi
|
||||
interfaces=$(/sbin/ip address show up | grep "^[0-9]*:" | grep -E -v "(lo|vnet|docker|veth|tun|tap|macvtap|vrrp|lxcbr|wg)" | cut -d " " -f 2 | tr -d : | cut -d@ -f1 | 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"
|
||||
|
@ -590,11 +452,9 @@ check_interfacesgw() {
|
|||
}
|
||||
# Verification de l’état du service networking
|
||||
check_networking_service() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
if systemctl is-enabled networking.service > /dev/null; then
|
||||
if ! systemctl is-active networking.service > /dev/null; then
|
||||
failed "IS_NETWORKING_SERVICE" "networking.service is not active"
|
||||
fi
|
||||
if systemctl is-enabled networking.service > /dev/null; then
|
||||
if ! systemctl is-active networking.service > /dev/null; then
|
||||
failed "IS_NETWORKING_SERVICE" "networking.service is not active"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
@ -674,23 +534,21 @@ check_apacheipinallow() {
|
|||
}
|
||||
# Check if default Apache configuration file for munin is absent (or empty or commented).
|
||||
check_muninapacheconf() {
|
||||
if is_debian_squeeze || is_debian_wheezy; then
|
||||
muninconf="/etc/apache2/conf.d/munin"
|
||||
else
|
||||
muninconf="/etc/apache2/conf-available/munin.conf"
|
||||
fi
|
||||
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
|
||||
}
|
||||
# Verification de la priorité du package samba si les backports sont utilisés
|
||||
check_sambainpriority() {
|
||||
if is_debian_lenny && is_pack_samba; then
|
||||
if grep -qrE "^[^#].*backport" /etc/apt/sources.list{,.d}; then
|
||||
priority=$(grep -E -A2 "^Package:.*samba" /etc/apt/preferences | grep -A1 "^Pin: release a=lenny-backports" | grep "^Pin-Priority:" | cut -f2 -d" ")
|
||||
test "$priority" -gt 500 || failed "IS_SAMBAPINPRIORITY" "bad pinning priority for samba"
|
||||
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.
|
||||
|
@ -833,60 +691,48 @@ check_tune2fs_m5() {
|
|||
done
|
||||
}
|
||||
check_evolinuxsudogroup() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
if grep -q "^evolinux-sudo:" /etc/group; then
|
||||
if [ -f /etc/sudoers.d/evolinux ]; then
|
||||
grep -qE '^%evolinux-sudo +ALL ?= ?\(ALL:ALL\) ALL' /etc/sudoers.d/evolinux \
|
||||
|| failed "IS_EVOLINUXSUDOGROUP" "missing evolinux-sudo directive in sudoers file"
|
||||
fi
|
||||
if grep -q "^evolinux-sudo:" /etc/group; then
|
||||
if [ -f /etc/sudoers.d/evolinux ]; then
|
||||
grep -qE '^%evolinux-sudo +ALL ?= ?\(ALL:ALL\) ALL' /etc/sudoers.d/evolinux \
|
||||
|| failed "IS_EVOLINUXSUDOGROUP" "missing evolinux-sudo directive in sudoers file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
check_userinadmgroup() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
users=$(grep "^evolinux-sudo:" /etc/group | awk -F: '{print $4}' | tr ',' ' ')
|
||||
for user in $users; do
|
||||
if ! groups "$user" | grep -q adm; then
|
||||
failed "IS_USERINADMGROUP" "User $user doesn't belong to \`adm' group"
|
||||
test "${VERBOSE}" = 1 || break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
users=$(grep "^evolinux-sudo:" /etc/group | awk -F: '{print $4}' | tr ',' ' ')
|
||||
for user in $users; do
|
||||
if ! groups "$user" | grep -q adm; then
|
||||
failed "IS_USERINADMGROUP" "User $user doesn't belong to \`adm' group"
|
||||
test "${VERBOSE}" = 1 || break
|
||||
fi
|
||||
done
|
||||
}
|
||||
check_apache2evolinuxconf() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
if is_installed apache2; then
|
||||
{ test -L /etc/apache2/conf-enabled/z-evolinux-defaults.conf \
|
||||
&& test -L /etc/apache2/conf-enabled/zzz-evolinux-custom.conf \
|
||||
&& test -f /etc/apache2/ipaddr_whitelist.conf;
|
||||
} || failed "IS_APACHE2EVOLINUXCONF" "missing custom evolinux apache config"
|
||||
fi
|
||||
if is_installed apache2; then
|
||||
{ test -L /etc/apache2/conf-enabled/z-evolinux-defaults.conf \
|
||||
&& test -L /etc/apache2/conf-enabled/zzz-evolinux-custom.conf \
|
||||
&& test -f /etc/apache2/ipaddr_whitelist.conf;
|
||||
} || failed "IS_APACHE2EVOLINUXCONF" "missing custom evolinux apache config"
|
||||
fi
|
||||
}
|
||||
check_backportsconf() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
grep -qsE "^[^#].*backports" /etc/apt/sources.list \
|
||||
&& failed "IS_BACKPORTSCONF" "backports can't be in main sources list"
|
||||
if grep -qsE "^[^#].*backports" /etc/apt/sources.list.d/*.list; then
|
||||
grep -qsE "^[^#].*backports" /etc/apt/preferences.d/* \
|
||||
|| failed "IS_BACKPORTSCONF" "backports must have preferences"
|
||||
fi
|
||||
grep -qsE "^[^#].*backports" /etc/apt/sources.list \
|
||||
&& failed "IS_BACKPORTSCONF" "backports can't be in main sources list"
|
||||
if grep -qsE "^[^#].*backports" /etc/apt/sources.list.d/*.list; then
|
||||
grep -qsE "^[^#].*backports" /etc/apt/preferences.d/* \
|
||||
|| failed "IS_BACKPORTSCONF" "backports must have preferences"
|
||||
fi
|
||||
}
|
||||
check_bind9munin() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
if is_installed bind9; then
|
||||
{ test -L /etc/munin/plugins/bind9 \
|
||||
&& test -e /etc/munin/plugin-conf.d/bind9;
|
||||
} || failed "IS_BIND9MUNIN" "missing bind plugin for munin"
|
||||
fi
|
||||
if is_installed bind9; 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_bind9logrotate() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
if is_installed bind9; then
|
||||
test -e /etc/logrotate.d/bind9 || failed "IS_BIND9LOGROTATE" "missing bind logrotate file"
|
||||
fi
|
||||
if is_installed bind9; then
|
||||
test -e /etc/logrotate.d/bind9 || failed "IS_BIND9LOGROTATE" "missing bind logrotate file"
|
||||
fi
|
||||
}
|
||||
check_broadcomfirmware() {
|
||||
|
@ -917,14 +763,12 @@ check_hardwareraidtool() {
|
|||
fi
|
||||
}
|
||||
check_log2mailsystemdunit() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
systemctl -q is-active log2mail.service \
|
||||
|| failed "IS_LOG2MAILSYSTEMDUNIT" "log2mail unit not running"
|
||||
test -f /etc/systemd/system/log2mail.service \
|
||||
|| failed "IS_LOG2MAILSYSTEMDUNIT" "missing log2mail unit file"
|
||||
test -f /etc/init.d/log2mail \
|
||||
&& failed "IS_LOG2MAILSYSTEMDUNIT" "/etc/init.d/log2mail may be deleted (use systemd unit)"
|
||||
fi
|
||||
systemctl -q is-active log2mail.service \
|
||||
|| failed "IS_LOG2MAILSYSTEMDUNIT" "log2mail unit not running"
|
||||
test -f /etc/systemd/system/log2mail.service \
|
||||
|| failed "IS_LOG2MAILSYSTEMDUNIT" "missing log2mail unit file"
|
||||
test -f /etc/init.d/log2mail \
|
||||
&& failed "IS_LOG2MAILSYSTEMDUNIT" "/etc/init.d/log2mail may be deleted (use systemd unit)"
|
||||
}
|
||||
check_listupgrade() {
|
||||
test -f /etc/cron.d/listupgrade \
|
||||
|
@ -933,13 +777,11 @@ check_listupgrade() {
|
|||
|| failed "IS_LISTUPGRADE" "missing listupgrade script or not executable"
|
||||
}
|
||||
check_mariadbevolinuxconf() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
if is_installed mariadb-server; then
|
||||
{ test -f /etc/mysql/mariadb.conf.d/z-evolinux-defaults.cnf \
|
||||
&& test -f /etc/mysql/mariadb.conf.d/zzz-evolinux-custom.cnf;
|
||||
} || failed "IS_MARIADBEVOLINUXCONF" "missing mariadb custom config"
|
||||
if is_installed mariadb-server; then
|
||||
{ test -f /etc/mysql/mariadb.conf.d/z-evolinux-defaults.cnf \
|
||||
&& test -f /etc/mysql/mariadb.conf.d/zzz-evolinux-custom.cnf;
|
||||
} || failed "IS_MARIADBEVOLINUXCONF" "missing mariadb custom config"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
check_sql_backup() {
|
||||
if (is_installed "mysql-server" || is_installed "mariadb-server"); then
|
||||
|
@ -997,8 +839,12 @@ check_ldap_backup() {
|
|||
check_redis_backup() {
|
||||
if is_installed redis-server; then
|
||||
# You could change the default path in /etc/evocheck.cf
|
||||
REDIS_BACKUP_PATH=${REDIS_BACKUP_PATH:-"/home/backup/dump.rdb"}
|
||||
test -f "$REDIS_BACKUP_PATH" || failed "IS_REDIS_BACKUP" "Redis dump is missing (${REDIS_BACKUP_PATH})"
|
||||
# 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() {
|
||||
|
@ -1020,73 +866,63 @@ check_mariadbsystemdunit() {
|
|||
fi
|
||||
}
|
||||
check_mysqlmunin() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
if is_installed mariadb-server; then
|
||||
for file in mysql_bytes mysql_queries mysql_slowqueries \
|
||||
mysql_threads mysql_connections mysql_files_tables \
|
||||
mysql_innodb_bpool mysql_innodb_bpool_act mysql_innodb_io \
|
||||
mysql_innodb_log mysql_innodb_rows mysql_innodb_semaphores \
|
||||
mysql_myisam_indexes mysql_qcache mysql_qcache_mem \
|
||||
mysql_sorts mysql_tmp_tables; do
|
||||
if is_installed mariadb-server; then
|
||||
for file in mysql_bytes mysql_queries mysql_slowqueries \
|
||||
mysql_threads mysql_connections mysql_files_tables \
|
||||
mysql_innodb_bpool mysql_innodb_bpool_act mysql_innodb_io \
|
||||
mysql_innodb_log mysql_innodb_rows mysql_innodb_semaphores \
|
||||
mysql_myisam_indexes mysql_qcache mysql_qcache_mem \
|
||||
mysql_sorts mysql_tmp_tables; do
|
||||
|
||||
if [[ ! -L /etc/munin/plugins/$file ]]; then
|
||||
failed "IS_MYSQLMUNIN" "missing munin plugin '$file'"
|
||||
test "${VERBOSE}" = 1 || break
|
||||
fi
|
||||
done
|
||||
munin-run mysql_commands 2> /dev/null > /dev/null
|
||||
test $? -eq 0 || failed "IS_MYSQLMUNIN" "Munin plugin mysql_commands returned an error"
|
||||
fi
|
||||
if [[ ! -L /etc/munin/plugins/$file ]]; then
|
||||
failed "IS_MYSQLMUNIN" "missing munin plugin '$file'"
|
||||
test "${VERBOSE}" = 1 || break
|
||||
fi
|
||||
done
|
||||
munin-run mysql_commands 2> /dev/null > /dev/null
|
||||
test $? -eq 0 || failed "IS_MYSQLMUNIN" "Munin plugin mysql_commands returned an error"
|
||||
fi
|
||||
}
|
||||
check_mysqlnrpe() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
if is_installed mariadb-server; then
|
||||
nagios_file=~nagios/.my.cnf
|
||||
if ! test -f ${nagios_file}; then
|
||||
failed "IS_MYSQLNRPE" "${nagios_file} is missing"
|
||||
elif [ "$(stat -c %U ${nagios_file})" != "nagios" ] \
|
||||
|| [ "$(stat -c %a ${nagios_file})" != "600" ]; then
|
||||
failed "IS_MYSQLNRPE" "${nagios_file} has wrong permissions"
|
||||
else
|
||||
grep -q -F "command[check_mysql]=/usr/lib/nagios/plugins/check_mysql" /etc/nagios/nrpe.d/evolix.cfg \
|
||||
|| failed "IS_MYSQLNRPE" "check_mysql is missing"
|
||||
fi
|
||||
if is_installed mariadb-server; then
|
||||
nagios_file=~nagios/.my.cnf
|
||||
if ! test -f ${nagios_file}; then
|
||||
failed "IS_MYSQLNRPE" "${nagios_file} is missing"
|
||||
elif [ "$(stat -c %U ${nagios_file})" != "nagios" ] \
|
||||
|| [ "$(stat -c %a ${nagios_file})" != "600" ]; then
|
||||
failed "IS_MYSQLNRPE" "${nagios_file} has wrong permissions"
|
||||
else
|
||||
grep -q -F "command[check_mysql]=/usr/lib/nagios/plugins/check_mysql" /etc/nagios/nrpe.d/evolix.cfg \
|
||||
|| failed "IS_MYSQLNRPE" "check_mysql is missing"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
check_phpevolinuxconf() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
is_debian_stretch && phpVersion="7.0"
|
||||
is_debian_buster && phpVersion="7.3"
|
||||
is_debian_bullseye && phpVersion="7.4"
|
||||
if is_installed php; then
|
||||
{ test -f /etc/php/${phpVersion}/cli/conf.d/z-evolinux-defaults.ini \
|
||||
&& test -f /etc/php/${phpVersion}/cli/conf.d/zzz-evolinux-custom.ini
|
||||
} || failed "IS_PHPEVOLINUXCONF" "missing php evolinux config"
|
||||
fi
|
||||
is_debian_stretch && phpVersion="7.0"
|
||||
is_debian_buster && phpVersion="7.3"
|
||||
is_debian_bullseye && phpVersion="7.4"
|
||||
if is_installed php; then
|
||||
{ test -f /etc/php/${phpVersion}/cli/conf.d/z-evolinux-defaults.ini \
|
||||
&& test -f /etc/php/${phpVersion}/cli/conf.d/zzz-evolinux-custom.ini
|
||||
} || failed "IS_PHPEVOLINUXCONF" "missing php evolinux config"
|
||||
fi
|
||||
}
|
||||
check_squidlogrotate() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
if is_installed squid; then
|
||||
grep -q -e monthly -e daily /etc/logrotate.d/squid \
|
||||
|| failed "IS_SQUIDLOGROTATE" "missing squid logrotate file"
|
||||
fi
|
||||
if is_installed squid; then
|
||||
grep -q -e monthly -e daily /etc/logrotate.d/squid \
|
||||
|| failed "IS_SQUIDLOGROTATE" "missing squid logrotate file"
|
||||
fi
|
||||
}
|
||||
check_squidevolinuxconf() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
if is_installed squid; then
|
||||
{ grep -qs "^CONFIG=/etc/squid/evolinux-defaults.conf$" /etc/default/squid \
|
||||
&& test -f /etc/squid/evolinux-defaults.conf \
|
||||
&& test -f /etc/squid/evolinux-whitelist-defaults.conf \
|
||||
&& test -f /etc/squid/evolinux-whitelist-custom.conf \
|
||||
&& test -f /etc/squid/evolinux-acl.conf \
|
||||
&& test -f /etc/squid/evolinux-httpaccess.conf \
|
||||
&& test -f /etc/squid/evolinux-custom.conf;
|
||||
} || failed "IS_SQUIDEVOLINUXCONF" "missing squid evolinux config"
|
||||
fi
|
||||
if is_installed squid; then
|
||||
{ grep -qs "^CONFIG=/etc/squid/evolinux-defaults.conf$" /etc/default/squid \
|
||||
&& test -f /etc/squid/evolinux-defaults.conf \
|
||||
&& test -f /etc/squid/evolinux-whitelist-defaults.conf \
|
||||
&& test -f /etc/squid/evolinux-whitelist-custom.conf \
|
||||
&& test -f /etc/squid/evolinux-acl.conf \
|
||||
&& test -f /etc/squid/evolinux-httpaccess.conf \
|
||||
&& test -f /etc/squid/evolinux-custom.conf;
|
||||
} || failed "IS_SQUIDEVOLINUXCONF" "missing squid evolinux config"
|
||||
fi
|
||||
}
|
||||
check_duplicate_fs_label() {
|
||||
|
@ -1152,41 +988,20 @@ 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 is_debian_jessie || is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
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
|
||||
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 Stretch, detection is easy as the kernel use
|
||||
# /sys/devices/system/cpu/vulnerabilities/
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
for vuln in meltdown spectre_v1 spectre_v2; do
|
||||
test -f "/sys/devices/system/cpu/vulnerabilities/$vuln" \
|
||||
|| failed "IS_MELTDOWN_SPECTRE" "vulnerable to $vuln"
|
||||
test "${VERBOSE}" = 1 || break
|
||||
done
|
||||
# For Jessie this is quite complicated to verify and we need to use kernel config file
|
||||
elif is_debian_jessie; then
|
||||
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
|
||||
fi
|
||||
for vuln in meltdown spectre_v1 spectre_v2; do
|
||||
test -f "/sys/devices/system/cpu/vulnerabilities/$vuln" \
|
||||
|| failed "IS_MELTDOWN_SPECTRE" "vulnerable to $vuln"
|
||||
test "${VERBOSE}" = 1 || break
|
||||
done
|
||||
}
|
||||
check_old_home_dir() {
|
||||
homeDir=${homeDir:-/home}
|
||||
|
@ -1218,7 +1033,7 @@ check_usrsharescripts() {
|
|||
}
|
||||
check_sshpermitrootno() {
|
||||
sshd_args="-C addr=,user=,host=,laddr=,lport=0"
|
||||
if is_debian_jessie || is_debian_stretch; then
|
||||
if is_debian_stretch; then
|
||||
# Noop, we'll use the default $sshd_args
|
||||
:
|
||||
elif is_debian_buster; then
|
||||
|
@ -1234,17 +1049,7 @@ check_sshpermitrootno() {
|
|||
fi
|
||||
}
|
||||
check_evomaintenanceusers() {
|
||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||
users=$(getent group evolinux-sudo | cut -d':' -f4 | tr ',' ' ')
|
||||
else
|
||||
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)
|
||||
fi
|
||||
users=$(getent group evolinux-sudo | cut -d':' -f4 | tr ',' ' ')
|
||||
for user in $users; do
|
||||
user_home=$(getent passwd "$user" | cut -d: -f6)
|
||||
if [ -n "$user_home" ] && [ -d "$user_home" ]; then
|
||||
|
@ -1307,17 +1112,6 @@ check_osprober() {
|
|||
fi
|
||||
}
|
||||
|
||||
check_jessie_backports() {
|
||||
if is_debian_jessie; then
|
||||
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
|
||||
fi
|
||||
}
|
||||
|
||||
check_apt_valid_until() {
|
||||
aptvalidFile="/etc/apt/apt.conf.d/99no-check-valid-until"
|
||||
aptvalidText="Acquire::Check-Valid-Until no;"
|
||||
|
@ -1356,14 +1150,8 @@ check_nginx_letsencrypt_uptodate() {
|
|||
snippets=$(find /etc/nginx -type f -name "letsencrypt.conf")
|
||||
if [ -n "${snippets}" ]; then
|
||||
while read -r snippet; do
|
||||
if is_debian_jessie; then
|
||||
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
|
||||
else
|
||||
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 9+."
|
||||
fi
|
||||
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 9+."
|
||||
fi
|
||||
done <<< "${snippets}"
|
||||
fi
|
||||
|
@ -1399,11 +1187,7 @@ download_versions() {
|
|||
# evoacme 21.06
|
||||
# evomaintenance 0.6.4
|
||||
|
||||
if is_debian; then
|
||||
versions_url="https://upgrades.evolix.org/versions-${DEBIAN_RELEASE}"
|
||||
else
|
||||
failed "IS_CHECK_VERSIONS" "error determining os release"
|
||||
fi
|
||||
versions_url="https://upgrades.evolix.org/versions-${DEBIAN_RELEASE}"
|
||||
|
||||
# fetch timeout, in seconds
|
||||
timeout=10
|
||||
|
@ -1527,8 +1311,6 @@ main() {
|
|||
main_output_file=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.main.XXXXX")
|
||||
files_to_cleanup="${files_to_cleanup} ${main_output_file}"
|
||||
|
||||
MINIFW_FILE=$(minifirewall_file)
|
||||
|
||||
test "${IS_TMP_1777:=1}" = 1 && check_tmp_1777
|
||||
test "${IS_ROOT_0700:=1}" = 1 && check_root_0700
|
||||
test "${IS_USRSHARESCRIPTS:=1}" = 1 && check_usrsharescripts
|
||||
|
@ -1540,19 +1322,15 @@ main() {
|
|||
|
||||
test "${IS_LSBRELEASE:=1}" = 1 && check_lsbrelease
|
||||
test "${IS_DPKGWARNING:=1}" = 1 && check_dpkgwarning
|
||||
test "${IS_UMASKSUDOERS:=1}" = 1 && check_umasksudoers
|
||||
test "${IS_NRPEPOSTFIX:=1}" = 1 && check_nrpepostfix
|
||||
test "${IS_MODSECURITY:=1}" = 1 && check_modsecurity
|
||||
test "${IS_CUSTOMSUDOERS:=1}" = 1 && check_customsudoers
|
||||
test "${IS_VARTMPFS:=1}" = 1 && check_vartmpfs
|
||||
test "${IS_SERVEURBASE:=1}" = 1 && check_serveurbase
|
||||
test "${IS_LOGROTATECONF:=1}" = 1 && check_logrotateconf
|
||||
test "${IS_SYSLOGCONF:=1}" = 1 && check_syslogconf
|
||||
test "${IS_DEBIANSECURITY:=1}" = 1 && check_debiansecurity
|
||||
test "${IS_APTITUDEONLY:=1}" = 1 && check_aptitudeonly
|
||||
test "${IS_APTITUDE:=1}" = 1 && check_aptitude
|
||||
test "${IS_APTGETBAK:=1}" = 1 && check_aptgetbak
|
||||
test "${IS_APTICRON:=0}" = 1 && check_apticron
|
||||
test "${IS_USRRO:=1}" = 1 && check_usrro
|
||||
test "${IS_TMPNOEXEC:=1}" = 1 && check_tmpnoexec
|
||||
test "${IS_MOUNT_FSTAB:=1}" = 1 && check_mountfstab
|
||||
|
@ -1584,7 +1362,6 @@ main() {
|
|||
test "${IS_LOG2MAILMYSQL:=1}" = 1 && check_log2mailmysql
|
||||
test "${IS_LOG2MAILSQUID:=1}" = 1 && check_log2mailsquid
|
||||
test "${IS_BINDCHROOT:=1}" = 1 && check_bindchroot
|
||||
test "${IS_REPVOLATILE:=1}" = 1 && check_repvolatile
|
||||
test "${IS_NETWORK_INTERFACES:=1}" = 1 && check_network_interfaces
|
||||
test "${IS_AUTOIF:=1}" = 1 && check_autoif
|
||||
test "${IS_INTERFACESGW:=1}" = 1 && check_interfacesgw
|
||||
|
@ -1596,7 +1373,7 @@ main() {
|
|||
test "${IS_APACHESYMLINK:=1}" = 1 && check_apachesymlink
|
||||
test "${IS_APACHEIPINALLOW:=1}" = 1 && check_apacheipinallow
|
||||
test "${IS_MUNINAPACHECONF:=1}" = 1 && check_muninapacheconf
|
||||
test "${IS_SAMBAPINPRIORITY:=1}" = 1 && check_sambainpriority
|
||||
test "${IS_PHPMYADMINAPACHECONF:=1}" = 1 && check_phpmyadminapacheconf
|
||||
test "${IS_KERNELUPTODATE:=1}" = 1 && check_kerneluptodate
|
||||
test "${IS_UPTIME:=1}" = 1 && check_uptime
|
||||
test "${IS_MUNINRUNNING:=1}" = 1 && check_muninrunning
|
||||
|
@ -1637,7 +1414,6 @@ main() {
|
|||
test "${IS_OLD_HOME_DIR:=0}" = 1 && check_old_home_dir
|
||||
test "${IS_EVOBACKUP_INCS:=1}" = 1 && check_evobackup_incs
|
||||
test "${IS_OSPROBER:=1}" = 1 && check_osprober
|
||||
test "${IS_JESSIE_BACKPORTS:=1}" = 1 && check_jessie_backports
|
||||
test "${IS_APT_VALID_UNTIL:=1}" = 1 && check_apt_valid_until
|
||||
test "${IS_CHROOTED_BINARY_UPTODATE:=1}" = 1 && check_chrooted_binary_uptodate
|
||||
test "${IS_NGINX_LETSENCRYPT_UPTODATE:=1}" = 1 && check_nginx_letsencrypt_uptodate
|
||||
|
|
1252
evocheck/files/evocheck.wheezy.sh
Executable file
1252
evocheck/files/evocheck.wheezy.sh
Executable file
|
@ -0,0 +1,1252 @@
|
|||
#!/bin/bash
|
||||
|
||||
# EvoCheck
|
||||
# Script to verify compliance of a Linux (Debian) server
|
||||
# powered by Evolix
|
||||
|
||||
VERSION="22.11"
|
||||
readonly VERSION
|
||||
|
||||
# base functions
|
||||
|
||||
show_version() {
|
||||
cat <<END
|
||||
evocheck version ${VERSION} (Wheezy)
|
||||
|
||||
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 "7" ]; then
|
||||
echo "Debian ${DEBIAN_MAIN_VERSION} is incompatible with this version of evocheck." >&2
|
||||
echo "This version is built for Debian 7 only." >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ -x "${LSB_RELEASE_BIN}" ]; then
|
||||
DEBIAN_RELEASE=$(${LSB_RELEASE_BIN} --codename --short)
|
||||
else
|
||||
case ${DEBIAN_MAIN_VERSION} in
|
||||
5) DEBIAN_RELEASE="lenny";;
|
||||
6) DEBIAN_RELEASE="squeeze";;
|
||||
7) DEBIAN_RELEASE="wheezy";;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
is_debian_lenny() {
|
||||
test "${DEBIAN_RELEASE}" = "lenny"
|
||||
}
|
||||
is_debian_squeeze() {
|
||||
test "${DEBIAN_RELEASE}" = "squeeze"
|
||||
}
|
||||
is_debian_wheezy() {
|
||||
test "${DEBIAN_RELEASE}" = "wheezy"
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
check_dpkgwarning() {
|
||||
if [ "$IS_USRRO" = 1 ] || [ "$IS_TMPNOEXEC" = 1 ]; then
|
||||
test -e /etc/apt/apt.conf.d/80evolinux \
|
||||
|| failed "IS_DPKGWARNING" "/etc/apt/apt.conf.d/80evolinux is missing"
|
||||
test -e /etc/apt/apt.conf \
|
||||
&& failed "IS_DPKGWARNING" "/etc/apt/apt.conf is missing"
|
||||
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_modsecurity() {
|
||||
if is_installed libapache2-modsecurity; then
|
||||
test -e /etc/apache2/conf.d/mod-security2.conf || failed "IS_MODSECURITY" "missing configuration file"
|
||||
fi
|
||||
}
|
||||
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_aptitudeonly() {
|
||||
test -e /usr/bin/apt-get && failed "IS_APTITUDEONLY" \
|
||||
"only aptitude may be enabled on Debian <=7, apt-get should be disabled"
|
||||
}
|
||||
|
||||
check_apticron() {
|
||||
status="OK"
|
||||
test -e /etc/cron.d/apticron || status="fail"
|
||||
test -e /etc/cron.daily/apticron && status="fail"
|
||||
test "$status" = "fail" || test -e /usr/bin/apt-get.bak || status="fail"
|
||||
|
||||
test "$status" = "fail" && failed "IS_APTICRON" "apticron must be in cron.d not cron.daily"
|
||||
}
|
||||
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/firewall.rc" ]; then
|
||||
actual=$(stat --format "%a" "/etc/firewall.rc")
|
||||
expected="600"
|
||||
test "$expected" = "$actual" || failed "IS_MINIFWPERMS" "/etc/firewall.rc 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/firewall.rc" \
|
||||
&& grep -qE "^[^#]*iptables -t nat -A OUTPUT -p tcp --dport 80 -d $host -j ACCEPT" "/etc/firewall.rc" \
|
||||
&& grep -qE "^[^#]*iptables -t nat -A OUTPUT -p tcp --dport 80 -d 127.0.0.(1|0/8) -j ACCEPT" "/etc/firewall.rc" \
|
||||
&& grep -qE "^[^#]*iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port.* $http_port" "/etc/firewall.rc";
|
||||
} || grep -qE "^PROXY='?on'?" "/etc/firewall.rc" \
|
||||
|| failed "IS_SQUID" "missing squid rules in minifirewall"
|
||||
fi
|
||||
}
|
||||
check_evomaintenance_fw() {
|
||||
if [ -f "/etc/firewall.rc" ]; 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/firewall.rc")
|
||||
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.d/munin"
|
||||
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_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_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() {
|
||||
# shellcheck disable=SC2086
|
||||
if ! (sshd -T 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_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_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:-}
|
||||
|
||||
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
|
||||
# ;;
|
||||
|
||||
add-vm)
|
||||
grep '^VERSION=' "${command}" | head -1 | cut -d '=' -f 2
|
||||
;;
|
||||
minifirewall)
|
||||
${command} version | head -1 | cut -d ' ' -f 3
|
||||
;;
|
||||
## Let's try the --version flag before falling back to grep for the constant
|
||||
kvmstats)
|
||||
if ${command} --version > /dev/null 2> /dev/null; then
|
||||
${command} --version 2> /dev/null | head -1 | cut -d ' ' -f 3
|
||||
else
|
||||
grep '^VERSION=' "${command}" | head -1 | cut -d '=' -f 2
|
||||
fi
|
||||
;;
|
||||
|
||||
## 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
|
||||
# shellcheck disable=SC2086
|
||||
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_CHECK_VERSIONS" "failed to lookup actual version of ${program}"
|
||||
elif dpkg --compare-versions "${actual_version}" lt "${expected_version}"; then
|
||||
failed "IS_CHECK_VERSIONS" "${program} version ${actual_version} is older than expected version ${expected_version}"
|
||||
elif dpkg --compare-versions "${actual_version}" gt "${expected_version}"; then
|
||||
failed "IS_CHECK_VERSIONS" "${program} version ${actual_version} is newer than expected version ${expected_version}, you should update your index."
|
||||
else
|
||||
: # Version check OK
|
||||
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 --tmpdir="${TMPDIR:-/tmp}" "evocheck.versions.XXXXX")
|
||||
files_to_cleanup="${files_to_cleanup} ${versions_file}"
|
||||
|
||||
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_CHECK_VERSIONS" "failed to lookup expected version for ${program}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
# Default return code : 0 = no error
|
||||
RC=0
|
||||
# Detect operating system name, version and release
|
||||
detect_os
|
||||
|
||||
main_output_file=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.main.XXXXX")
|
||||
files_to_cleanup="${files_to_cleanup} ${main_output_file}"
|
||||
|
||||
test "${IS_TMP_1777:=1}" = 1 && check_tmp_1777
|
||||
test "${IS_ROOT_0700:=1}" = 1 && check_root_0700
|
||||
test "${IS_USRSHARESCRIPTS:=1}" = 1 && check_usrsharescripts
|
||||
test "${IS_SSHPERMITROOTNO:=1}" = 1 && check_sshpermitrootno
|
||||
test "${IS_EVOMAINTENANCEUSERS:=1}" = 1 && check_evomaintenanceusers
|
||||
# Verification de la configuration d'evomaintenance
|
||||
test "${IS_EVOMAINTENANCECONF:=1}" = 1 && check_evomaintenanceconf
|
||||
test "${IS_PRIVKEYWOLRDREADABLE:=1}" = 1 && check_privatekeyworldreadable
|
||||
|
||||
test "${IS_LSBRELEASE:=1}" = 1 && check_lsbrelease
|
||||
test "${IS_DPKGWARNING:=1}" = 1 && check_dpkgwarning
|
||||
test "${IS_NRPEPOSTFIX:=1}" = 1 && check_nrpepostfix
|
||||
test "${IS_MODSECURITY:=1}" = 1 && check_modsecurity
|
||||
test "${IS_CUSTOMSUDOERS:=1}" = 1 && check_customsudoers
|
||||
test "${IS_VARTMPFS:=1}" = 1 && check_vartmpfs
|
||||
test "${IS_SERVEURBASE:=1}" = 1 && check_serveurbase
|
||||
test "${IS_LOGROTATECONF:=1}" = 1 && check_logrotateconf
|
||||
test "${IS_SYSLOGCONF:=1}" = 1 && check_syslogconf
|
||||
test "${IS_DEBIANSECURITY:=1}" = 1 && check_debiansecurity
|
||||
test "${IS_APTITUDEONLY:=1}" = 1 && check_aptitudeonly
|
||||
test "${IS_APTICRON:=0}" = 1 && check_apticron
|
||||
test "${IS_USRRO:=1}" = 1 && check_usrro
|
||||
test "${IS_TMPNOEXEC:=1}" = 1 && check_tmpnoexec
|
||||
test "${IS_MOUNT_FSTAB:=1}" = 1 && check_mountfstab
|
||||
test "${IS_LISTCHANGESCONF:=1}" = 1 && check_listchangesconf
|
||||
test "${IS_CUSTOMCRONTAB:=1}" = 1 && check_customcrontab
|
||||
test "${IS_SSHALLOWUSERS:=1}" = 1 && check_sshallowusers
|
||||
test "${IS_DISKPERF:=0}" = 1 && check_diskperf
|
||||
test "${IS_TMOUTPROFILE:=1}" = 1 && check_tmoutprofile
|
||||
test "${IS_ALERT5BOOT:=1}" = 1 && check_alert5boot
|
||||
test "${IS_ALERT5MINIFW:=1}" = 1 && check_alert5minifw
|
||||
test "${IS_ALERT5MINIFW:=1}" = 1 && test "${IS_MINIFW:=1}" = 1 && check_minifw
|
||||
test "${IS_NRPEPERMS:=1}" = 1 && check_nrpeperms
|
||||
test "${IS_MINIFWPERMS:=1}" = 1 && check_minifwperms
|
||||
test "${IS_NRPEDISKS:=0}" = 1 && check_nrpedisks
|
||||
test "${IS_NRPEPID:=1}" = 1 && check_nrpepid
|
||||
test "${IS_GRSECPROCS:=1}" = 1 && check_grsecprocs
|
||||
test "${IS_APACHEMUNIN:=1}" = 1 && check_apachemunin
|
||||
test "${IS_MYSQLUTILS:=1}" = 1 && check_mysqlutils
|
||||
test "${IS_RAIDSOFT:=1}" = 1 && check_raidsoft
|
||||
test "${IS_AWSTATSLOGFORMAT:=1}" = 1 && check_awstatslogformat
|
||||
test "${IS_MUNINLOGROTATE:=1}" = 1 && check_muninlogrotate
|
||||
test "${IS_SQUID:=1}" = 1 && check_squid
|
||||
test "${IS_EVOMAINTENANCE_FW:=1}" = 1 && check_evomaintenance_fw
|
||||
test "${IS_MODDEFLATE:=1}" = 1 && check_moddeflate
|
||||
test "${IS_LOG2MAILRUNNING:=1}" = 1 && check_log2mailrunning
|
||||
test "${IS_LOG2MAILAPACHE:=1}" = 1 && check_log2mailapache
|
||||
test "${IS_LOG2MAILMYSQL:=1}" = 1 && check_log2mailmysql
|
||||
test "${IS_LOG2MAILSQUID:=1}" = 1 && check_log2mailsquid
|
||||
test "${IS_BINDCHROOT:=1}" = 1 && check_bindchroot
|
||||
test "${IS_NETWORK_INTERFACES:=1}" = 1 && check_network_interfaces
|
||||
test "${IS_AUTOIF:=1}" = 1 && check_autoif
|
||||
test "${IS_INTERFACESGW:=1}" = 1 && check_interfacesgw
|
||||
test "${IS_EVOBACKUP:=1}" = 1 && check_evobackup
|
||||
test "${IS_EVOBACKUP_EXCLUDE_MOUNT:=1}" = 1 && check_evobackup_exclude_mount
|
||||
test "${IS_USERLOGROTATE:=1}" = 1 && check_userlogrotate
|
||||
test "${IS_APACHECTL:=1}" = 1 && check_apachectl
|
||||
test "${IS_APACHESYMLINK:=1}" = 1 && check_apachesymlink
|
||||
test "${IS_APACHEIPINALLOW:=1}" = 1 && check_apacheipinallow
|
||||
test "${IS_MUNINAPACHECONF:=1}" = 1 && check_muninapacheconf
|
||||
test "${IS_PHPMYADMINAPACHECONF:=1}" = 1 && check_phpmyadminapacheconf
|
||||
test "${IS_KERNELUPTODATE:=1}" = 1 && check_kerneluptodate
|
||||
test "${IS_UPTIME:=1}" = 1 && check_uptime
|
||||
test "${IS_MUNINRUNNING:=1}" = 1 && check_muninrunning
|
||||
test "${IS_BACKUPUPTODATE:=1}" = 1 && check_backupuptodate
|
||||
test "${IS_ETCGIT:=1}" = 1 && check_etcgit
|
||||
test "${IS_GITPERMS:=1}" = 1 && check_gitperms
|
||||
test "${IS_NOTUPGRADED:=1}" = 1 && check_notupgraded
|
||||
test "${IS_TUNE2FS_M5:=1}" = 1 && check_tune2fs_m5
|
||||
test "${IS_BROADCOMFIRMWARE:=1}" = 1 && check_broadcomfirmware
|
||||
test "${IS_HARDWARERAIDTOOL:=1}" = 1 && check_hardwareraidtool
|
||||
test "${IS_SQL_BACKUP:=1}" = 1 && check_sql_backup
|
||||
test "${IS_POSTGRES_BACKUP:=1}" = 1 && check_postgres_backup
|
||||
test "${IS_MONGO_BACKUP:=1}" = 1 && check_mongo_backup
|
||||
test "${IS_LDAP_BACKUP:=1}" = 1 && check_ldap_backup
|
||||
test "${IS_REDIS_BACKUP:=1}" = 1 && check_redis_backup
|
||||
test "${IS_ELASTIC_BACKUP:=1}" = 1 && check_elastic_backup
|
||||
test "${IS_DUPLICATE_FS_LABEL:=1}" = 1 && check_duplicate_fs_label
|
||||
test "${IS_EVOLIX_USER:=1}" = 1 && check_evolix_user
|
||||
test "${IS_OLD_HOME_DIR:=0}" = 1 && check_old_home_dir
|
||||
test "${IS_EVOBACKUP_INCS:=1}" = 1 && check_evobackup_incs
|
||||
test "${IS_OSPROBER:=1}" = 1 && check_osprober
|
||||
test "${IS_APT_VALID_UNTIL:=1}" = 1 && check_apt_valid_until
|
||||
test "${IS_CHROOTED_BINARY_UPTODATE:=1}" = 1 && check_chrooted_binary_uptodate
|
||||
test "${IS_CHECK_VERSIONS:=1}" = 1 && check_versions
|
||||
|
||||
if [ -f "${main_output_file}" ]; then
|
||||
lines_found=$(wc -l < "${main_output_file}")
|
||||
# shellcheck disable=SC2086
|
||||
if [ ${lines_found} -gt 0 ]; then
|
||||
|
||||
cat "${main_output_file}" 2>&1
|
||||
fi
|
||||
fi
|
||||
|
||||
exit ${RC}
|
||||
}
|
||||
cleanup_temp_files() {
|
||||
# shellcheck disable=SC2086
|
||||
rm -f ${files_to_cleanup}
|
||||
}
|
||||
|
||||
PROGNAME=$(basename "$0")
|
||||
# shellcheck disable=SC2034
|
||||
readonly PROGNAME
|
||||
|
||||
# shellcheck disable=SC2124
|
||||
ARGS=$@
|
||||
readonly ARGS
|
||||
|
||||
# Disable LANG*
|
||||
export LANG=C
|
||||
export LANGUAGE=C
|
||||
|
||||
files_to_cleanup=""
|
||||
# shellcheck disable=SC2064
|
||||
trap cleanup_temp_files 0
|
||||
|
||||
# Source configuration file
|
||||
# shellcheck disable=SC1091
|
||||
test -f /etc/evocheck.cf && . /etc/evocheck.cf
|
||||
|
||||
# Parse options
|
||||
# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
|
||||
while :; do
|
||||
case $1 in
|
||||
-h|-\?|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
--version)
|
||||
show_version
|
||||
exit 0
|
||||
;;
|
||||
--cron)
|
||||
IS_KERNELUPTODATE=0
|
||||
IS_UPTIME=0
|
||||
IS_MELTDOWN_SPECTRE=0
|
||||
IS_CHECK_VERSIONS=0
|
||||
IS_NETWORKING_SERVICE=0
|
||||
;;
|
||||
-v|--verbose)
|
||||
VERBOSE=1
|
||||
;;
|
||||
-q|--quiet)
|
||||
QUIET=1
|
||||
VERBOSE=0
|
||||
;;
|
||||
--)
|
||||
# End of all options.
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-?*|[[:alnum:]]*)
|
||||
# ignore unknown options
|
||||
if [ "${QUIET}" != 1 ]; then
|
||||
printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# Default case: If no more options then break out of the loop.
|
||||
break
|
||||
;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
main ${ARGS}
|
|
@ -15,9 +15,24 @@
|
|||
tags:
|
||||
- evocheck
|
||||
|
||||
- name: Script for Debian 7 and earlier
|
||||
set_fact:
|
||||
evocheck_script_src: evocheck.wheezy.sh
|
||||
when: ansible_distribution_major_version is version('7', '<=')
|
||||
|
||||
- name: Script for Debian 8
|
||||
set_fact:
|
||||
evocheck_script_src: evocheck.jessie.sh
|
||||
when: ansible_distribution_major_version is version('8', '=')
|
||||
|
||||
- name: Script for Debian 9 and later
|
||||
set_fact:
|
||||
evocheck_script_src: evocheck.sh
|
||||
when: ansible_distribution_major_version is version('9', '>=')
|
||||
|
||||
- name: Copy evocheck.sh
|
||||
copy:
|
||||
src: evocheck.sh
|
||||
src: "{{ evocheck_script_src }}"
|
||||
dest: "{{ evocheck_bin_dir }}/evocheck.sh"
|
||||
mode: "0700"
|
||||
owner: root
|
||||
|
|
|
@ -21,6 +21,8 @@ evolinux_apt_public_sources: True
|
|||
evolinux_apt_upgrade: True
|
||||
evolinux_apt_remove_aptitude: True
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
||||
|
||||
# etc-evolinux
|
||||
|
||||
evolinux_etcevolinux_include: True
|
||||
|
@ -48,6 +50,7 @@ evolinux_internal_fqdn: "{{ evolinux_internal_hostname }}.{{ evolinux_intern
|
|||
|
||||
evolinux_kernel_include: True
|
||||
|
||||
evolinux_kernel_cloud_auto: True
|
||||
evolinux_kernel_reboot_after_panic: True
|
||||
evolinux_kernel_disable_tcp_timestamps: True
|
||||
evolinux_kernel_customize_swappiness: True
|
||||
|
@ -224,3 +227,6 @@ evolinux_cron_checkhpraid_frequency: daily
|
|||
|
||||
# Motd
|
||||
evolinux_motd_include: True
|
||||
|
||||
# Utils
|
||||
evolinux_utils_include: True
|
|
@ -81,7 +81,7 @@
|
|||
- name: HPE GPG key is installed
|
||||
copy:
|
||||
src: hpePublicKey2048_key1.asc
|
||||
dest: /etc/apt/trusted.gpg.d/hpePublicKey2048_key1.asc
|
||||
dest: "{{ apt_keyring_dir }}/hpePublicKey2048_key1.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
|
@ -91,11 +91,18 @@
|
|||
|
||||
- name: Add HPE repository
|
||||
apt_repository:
|
||||
repo: 'deb https://downloads.linux.hpe.com/SDR/repo/mcp {{ ansible_distribution_release }}/current non-free'
|
||||
repo: 'deb [signed-by={{ apt_keyring_dir }}/hpePublicKey2048_key1.asc] https://downloads.linux.hpe.com/SDR/repo/mcp {{ ansible_distribution_release }}/current non-free'
|
||||
state: present
|
||||
tags:
|
||||
- packages
|
||||
|
||||
- name: Remove unsigned HPE repository
|
||||
apt_repository:
|
||||
repo: 'deb https://downloads.linux.hpe.com/SDR/repo/mcp {{ ansible_distribution_release }}/current non-free'
|
||||
state: absent
|
||||
tags:
|
||||
- packages
|
||||
|
||||
- name: Install HPE Smart Storage Administrator (ssacli)
|
||||
apt:
|
||||
name: ssacli
|
||||
|
@ -208,7 +215,7 @@
|
|||
- name: HWRaid GPG key is installed
|
||||
copy:
|
||||
src: hwraid.le-vert.net.asc
|
||||
dest: /etc/apt/trusted.gpg.d/hwraid.le-vert.net.asc
|
||||
dest: "{{ apt_keyring_dir }}/hwraid.le-vert.net.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
|
@ -219,11 +226,18 @@
|
|||
|
||||
- name: Add HW tool repository
|
||||
apt_repository:
|
||||
repo: 'deb http://hwraid.le-vert.net/debian {{ ansible_distribution_release }} main'
|
||||
repo: 'deb [signed-by={{ apt_keyring_dir }}/hwraid.le-vert.net.asc] http://hwraid.le-vert.net/debian {{ ansible_distribution_release }} main'
|
||||
state: present
|
||||
tags:
|
||||
- packages
|
||||
|
||||
- name: Remove unsigned HW tool repository
|
||||
apt_repository:
|
||||
repo: 'deb http://hwraid.le-vert.net/debian {{ ansible_distribution_release }} main'
|
||||
state: absent
|
||||
tags:
|
||||
- packages
|
||||
|
||||
- name: Install packages for DELL/LSI hardware
|
||||
apt:
|
||||
name:
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
- name: Deploy htop configuration
|
||||
copy:
|
||||
src: htoprc
|
||||
dest: /etc/htoprc
|
||||
mode: "0644"
|
|
@ -1,5 +1,23 @@
|
|||
---
|
||||
|
||||
- name: "Use Cloud kernel on virtual servers"
|
||||
apt:
|
||||
name: "linux-image-cloud-amd64"
|
||||
state: present
|
||||
when:
|
||||
- ansible_machine == "x86_64"
|
||||
- ansible_virtualization_role == "guest"
|
||||
- evolinux_kernel_cloud_auto | bool
|
||||
|
||||
- name: "Remove non-Cloud kernel on virtual servers"
|
||||
apt:
|
||||
name: "linux-image-amd64"
|
||||
state: absent
|
||||
when:
|
||||
- ansible_machine == "x86_64"
|
||||
- ansible_virtualization_role == "guest"
|
||||
- evolinux_kernel_cloud_auto | bool
|
||||
|
||||
- name: Reboot after panic
|
||||
sysctl:
|
||||
name: "{{ item.name }}"
|
||||
|
|
|
@ -102,6 +102,7 @@
|
|||
when: evolinux_motd_include | bool
|
||||
|
||||
- include: utils.yml
|
||||
when: evolinux_utils_include | bool
|
||||
|
||||
- name: Munin
|
||||
include_role:
|
||||
|
@ -132,7 +133,3 @@
|
|||
include_role:
|
||||
name: evolix/generate-ldif
|
||||
when: evolinux_generateldif_include | bool
|
||||
|
||||
- include: top.yml
|
||||
|
||||
- include: htop.yml
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
- name: Deploy top configuration file
|
||||
file:
|
||||
path: /etc/topdefaultrc
|
||||
state: absent
|
|
@ -38,3 +38,14 @@
|
|||
# owner: root
|
||||
# group: root
|
||||
# mode: "0755"
|
||||
|
||||
- name: Deploy htop configuration
|
||||
copy:
|
||||
src: htoprc
|
||||
dest: /etc/htoprc
|
||||
mode: "0644"
|
||||
|
||||
- name: Deploy top configuration file
|
||||
file:
|
||||
path: /etc/topdefaultrc
|
||||
state: absent
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
dest: /etc/evolinux
|
||||
mode: "0700"
|
||||
state: directory
|
||||
when: ansible_distribution == "Debian"
|
||||
|
||||
- name: /etc/evolinux/todo.txt is present
|
||||
copy:
|
||||
|
@ -12,3 +13,4 @@
|
|||
dest: /etc/evolinux/todo.txt
|
||||
mode: "0640"
|
||||
force: no
|
||||
when: ansible_distribution == "Debian"
|
||||
|
|
|
@ -12,7 +12,8 @@ nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_phpfpm_multi
|
|||
nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_phpfpm_multi /var/lib/lxc/php70/rootfs/etc/php/7.0/fpm/pool.d/
|
||||
nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_phpfpm_multi /var/lib/lxc/php73/rootfs/etc/php/7.3/fpm/pool.d/
|
||||
nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_phpfpm_multi /var/lib/lxc/php74/rootfs/etc/php/7.4/fpm/pool.d/
|
||||
nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_phpfpm_multi /var/lib/lxc/php74/rootfs/etc/php/8.0/fpm/pool.d/
|
||||
nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_phpfpm_multi /var/lib/lxc/php80/rootfs/etc/php/8.0/fpm/pool.d/
|
||||
nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_phpfpm_multi /var/lib/lxc/php81/rootfs/etc/php/8.1/fpm/pool.d/
|
||||
nagios ALL = NOPASSWD: /usr/sbin/megaclisas-status --nagios
|
||||
nagios ALL = NOPASSWD: /usr/lib/nagios/plugins/check_ipmi_sensor
|
||||
nagios ALL = NOPASSWD: /sbin/dmsetup status --noflush
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
- evomaintenance_api_endpoint is not none
|
||||
- evomaintenance_api_key is not none
|
||||
msg: evomaintenance api variables must be set
|
||||
when: evomaintenance_hook_api | bool
|
||||
|
||||
- name: Configuration is installed
|
||||
template:
|
||||
|
|
|
@ -11,7 +11,7 @@ FULLFROM="{{ evomaintenance_full_from }}"
|
|||
URGENCYFROM={{ evomaintenance_urgency_from }}
|
||||
URGENCYTEL="{{ evomaintenance_urgency_tel }}"
|
||||
REALM="{{ evomaintenance_realm }}"
|
||||
API_ENDPOINT={{ evomaintenance_api_endpoint }}
|
||||
API_ENDPOINT={{ evomaintenance_api_endpoint }}
|
||||
API_KEY={{ evomaintenance_api_key }}
|
||||
|
||||
HOOK_API={{ evomaintenance_hook_api | bool | ternary('1','0') }}
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
#!/bin/sh
|
||||
# Juin 2022 : #64088
|
||||
/usr/bin/sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "DELETE FROM bans WHERE date('now', '-{{ fail2ban_recidive_bantime | default(default_dbpurgeage.stdout) }}') > datetime(timeofban, 'unixepoch'); VACUUM;"
|
||||
# Juin - Decembre 2022 : #64088
|
||||
# Purge pour Stretch et Buster
|
||||
|
||||
/usr/bin/ionice -c3 /usr/bin/sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "DELETE FROM bans WHERE datetime('now', '-{{ bantime.stdout }} second') > datetime(timeofban, 'unixepoch');"
|
||||
|
||||
place_dispo=$( df -h /var/lib/fail2ban/fail2ban.sqlite3 --output="avail" -h --block-size=1 |tail -n1 )
|
||||
place_pris=$( echo $(("$(stat --format %s /var/lib/fail2ban/fail2ban.sqlite3 ) * 2" )) )
|
||||
|
||||
if [ $place_pris -lt $place_dispo ]
|
||||
then
|
||||
/usr/bin/ionice -c3 /usr/bin/sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "VACUUM;"
|
||||
fi
|
||||
|
|
|
@ -38,7 +38,7 @@ bantime = {{ fail2ban_recidive_bantime }}
|
|||
# Evolix custom jails
|
||||
|
||||
[wordpress-hard]
|
||||
enabled = {{ fail2ban_wordpress_hard }}
|
||||
enabled = {{ fail2ban_wordpress_hard }}
|
||||
port = http, https
|
||||
filter = wordpress-hard
|
||||
logpath = /var/log/auth.log
|
||||
|
@ -47,7 +47,7 @@ findtime = {{ fail2ban_wordpress_hard_findtime }}
|
|||
bantime = {{ fail2ban_wordpress_hard_bantime }}
|
||||
|
||||
[wordpress-soft]
|
||||
enabled = {{ fail2ban_wordpress_soft }}
|
||||
enabled = {{ fail2ban_wordpress_soft }}
|
||||
port = http, https
|
||||
filter = wordpress-soft
|
||||
logpath = /var/log/auth.log
|
||||
|
@ -56,7 +56,7 @@ findtime = {{ fail2ban_wordpress_soft_findtime }}
|
|||
bantime = {{ fail2ban_wordpress_soft_bantime }}
|
||||
|
||||
[roundcube]
|
||||
enabled = {{ fail2ban_roundcube }}
|
||||
enabled = {{ fail2ban_roundcube }}
|
||||
port = http, https
|
||||
filter = roundcube
|
||||
logpath = /var/lib/roundcube/logs/errors
|
||||
|
|
|
@ -22,3 +22,5 @@ filebeat_use_config_template: False
|
|||
filebeat_update_config: True
|
||||
filebeat_force_config: True
|
||||
filebeat_upgrade_package: False
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -29,7 +29,7 @@
|
|||
- name: Elastic GPG key is installed
|
||||
copy:
|
||||
src: elastic.asc
|
||||
dest: /etc/apt/trusted.gpg.d/elastic.asc
|
||||
dest: "{{ apt_keyring_dir }}/elastic.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
|
@ -40,7 +40,7 @@
|
|||
|
||||
- name: Elastic sources list is available
|
||||
apt_repository:
|
||||
repo: "deb https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
repo: "deb [signed-by={{ apt_keyring_dir }}/elastic.asc] https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
filename: elastic
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
@ -48,6 +48,16 @@
|
|||
- filebeat
|
||||
- packages
|
||||
|
||||
- name: Unsigned Elastic sources list is not available
|
||||
apt_repository:
|
||||
repo: "deb https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
filename: elastic
|
||||
state: absent
|
||||
update_cache: yes
|
||||
tags:
|
||||
- filebeat
|
||||
- packages
|
||||
|
||||
- name: Filebeat is installed
|
||||
apt:
|
||||
name: filebeat
|
||||
|
|
|
@ -10,3 +10,5 @@ fluentd_host_port:
|
|||
|
||||
fluentd_flush_interval:
|
||||
fluentd_heartbeat_type:
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -21,7 +21,7 @@
|
|||
- name: Add Fluentd GPG key
|
||||
copy:
|
||||
src: fluentd.asc
|
||||
dest: /etc/apt/trusted.gpg.d/fluentd.asc
|
||||
dest: "{{ apt_keyring_dir }}/fluentd.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
|
@ -32,7 +32,7 @@
|
|||
|
||||
- name: Fluentd sources list is available
|
||||
apt_repository:
|
||||
repo: "deb http://packages.treasuredata.com/3/debian/{{ ansible_distribution_release }}/ {{ ansible_distribution_release }} contrib"
|
||||
repo: "deb [signed-by={{ apt_keyring_dir }}/fluentd.asc] http://packages.treasuredata.com/3/debian/{{ ansible_distribution_release }}/ {{ ansible_distribution_release }} contrib"
|
||||
filename: treasuredata
|
||||
update_cache: yes
|
||||
state: present
|
||||
|
@ -40,6 +40,16 @@
|
|||
- packages
|
||||
- fluentd
|
||||
|
||||
- name: Unsigned Fluentd sources list is not available
|
||||
apt_repository:
|
||||
repo: "deb http://packages.treasuredata.com/3/debian/{{ ansible_distribution_release }}/ {{ ansible_distribution_release }} contrib"
|
||||
filename: treasuredata
|
||||
update_cache: yes
|
||||
state: absent
|
||||
tags:
|
||||
- packages
|
||||
- fluentd
|
||||
|
||||
- name: Fluentd is installed.
|
||||
apt:
|
||||
name: td-agent
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
---
|
||||
java_alternative: 'openjdk'
|
||||
java_version: 8
|
||||
java_version: Null
|
||||
java_default_alternative: True
|
||||
|
|
|
@ -13,7 +13,17 @@
|
|||
tags:
|
||||
- java
|
||||
|
||||
- name: Install openjdk package
|
||||
- name: Install default openjdk package
|
||||
apt:
|
||||
name: "default-jre-headless"
|
||||
default_release: "{{ java_apt_release }}"
|
||||
state: present
|
||||
tags:
|
||||
- java
|
||||
- packages
|
||||
when: java_version is none
|
||||
|
||||
- name: Install specific openjdk package
|
||||
apt:
|
||||
name: "openjdk-{{ java_version}}-jre-headless"
|
||||
default_release: "{{ java_apt_release }}"
|
||||
|
@ -21,11 +31,14 @@
|
|||
tags:
|
||||
- java
|
||||
- packages
|
||||
when: java_version is not none
|
||||
|
||||
- name: This openjdk version is the default alternative
|
||||
alternatives:
|
||||
name: java
|
||||
path: "{{ java_bin_path[java_version] }}"
|
||||
when: java_default_alternative | bool
|
||||
tags:
|
||||
- java
|
||||
when:
|
||||
- java_default_alternative | bool
|
||||
- java_version is not none
|
||||
|
|
3
jenkins/defaults/main.yml
Normal file
3
jenkins/defaults/main.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -20,17 +20,24 @@
|
|||
- name: Add Jenkins GPG key
|
||||
copy:
|
||||
src: jenkins.asc
|
||||
dest: /etc/apt/trusted.gpg.d/jenkins.asc
|
||||
dest: "{{ apt_keyring_dir }}/jenkins.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: Add jenkins APT repository
|
||||
apt_repository:
|
||||
repo: deb [signed-by={{ apt_keyring_dir }}/jenkins.asc] http://pkg.jenkins-ci.org/debian-stable binary/
|
||||
filename: jenkins
|
||||
update_cache: yes
|
||||
|
||||
- name: Remove unsigned jenkins APT repository
|
||||
apt_repository:
|
||||
repo: deb http://pkg.jenkins-ci.org/debian-stable binary/
|
||||
filename: jenkins
|
||||
update_cache: yes
|
||||
state: absent
|
||||
|
||||
- name: Install Jenkins
|
||||
apt:
|
||||
|
|
|
@ -18,35 +18,38 @@ MASTER='true'
|
|||
# checking if there are alive keepalived processes so we can trust the content of the notify 'state' file
|
||||
KEEPALIVENUM=`ps uax|grep '/usr/sbin/keepalived'|grep -v grep|wc -l|tr -d "\n"`
|
||||
|
||||
if [ $KEEPALIVENUM -gt 0 ]; then
|
||||
if [ ${KEEPALIVENUM} -gt 0 ]; then
|
||||
|
||||
KEEPALIVESTATE=`cat /var/run/keepalive.state`
|
||||
|
||||
if [ "$MASTER" == "true" ]; then
|
||||
if [ "${MASTER}" == "true" ]; then
|
||||
|
||||
if [[ $KEEPALIVESTATE == *"MASTER"* ]];then
|
||||
echo $KEEPALIVESTATE
|
||||
if [[ ${KEEPALIVESTATE} == *"MASTER"* ]];then
|
||||
echo "OK - ${KEEPALIVESTATE}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ $KEEPALIVESTATE == *"BACKUP"* ]];then
|
||||
echo $KEEPALIVESTATE
|
||||
exit 2
|
||||
if [[ ${KEEPALIVESTATE} == *"BACKUP"* ]];then
|
||||
echo "WARNING - ${KEEPALIVESTATE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
if [[ $KEEPALIVESTATE == *"BACKUP"* ]];then
|
||||
echo $KEEPALIVESTATE
|
||||
if [[ ${KEEPALIVESTATE} == *"BACKUP"* ]];then
|
||||
echo "OK - ${KEEPALIVESTATE}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ $KEEPALIVESTATE == *"MASTER"* ]];then
|
||||
echo $KEEPALIVESTATE
|
||||
exit 2
|
||||
if [[ ${KEEPALIVESTATE} == *"MASTER"* ]];then
|
||||
echo "WARNING - ${KEEPALIVESTATE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
fi
|
||||
else
|
||||
echo "CRITICAL - keepalived is not running"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
echo "Keepalived is in UNKNOWN state"
|
||||
|
|
|
@ -9,3 +9,5 @@ kibana_proxy_nginx: False
|
|||
kibana_proxy_domain: "kibana.{{ ansible_fqdn }}"
|
||||
kibana_proxy_ssl_cert: "/etc/ssl/certs/{{ ansible_fqdn }}.crt"
|
||||
kibana_proxy_ssl_key: "/etc/ssl/private/{{ ansible_fqdn }}.key"
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -29,7 +29,7 @@
|
|||
- name: Elastic GPG key is installed
|
||||
copy:
|
||||
src: elastic.asc
|
||||
dest: /etc/apt/trusted.gpg.d/elastic.asc
|
||||
dest: "{{ apt_keyring_dir }}/elastic.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
|
@ -40,7 +40,7 @@
|
|||
|
||||
- name: Elastic sources list is available
|
||||
apt_repository:
|
||||
repo: "deb https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
repo: "deb [signed-by={{ apt_keyring_dir }}/elastic.asc] https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
filename: elastic
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
@ -48,6 +48,16 @@
|
|||
- kibana
|
||||
- packages
|
||||
|
||||
- name: Unsigned Elastic sources list is not available
|
||||
apt_repository:
|
||||
repo: "deb https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
filename: elastic
|
||||
state: absent
|
||||
update_cache: yes
|
||||
tags:
|
||||
- kibana
|
||||
- packages
|
||||
|
||||
- name: Kibana is installed
|
||||
apt:
|
||||
name: kibana
|
||||
|
|
|
@ -100,15 +100,15 @@ semaine prochaine.
|
|||
|
||||
Voici la listes de packages qui seront mis à jour :
|
||||
|
||||
$(cat "${packages}")
|
||||
$(cat "${packages}" | sort | uniq)
|
||||
|
||||
Liste des packages dont la mise-à-jour a été manuellement suspendue :
|
||||
|
||||
$(cat "${packagesHold}")
|
||||
$(cat "${packagesHold}" | sort | uniq)
|
||||
|
||||
Liste des services qui seront redémarrés :
|
||||
|
||||
$(cat "${servicesToRestart}")
|
||||
$(cat "${servicesToRestart}" | sort | uniq)
|
||||
|
||||
N'hésitez pas à nous faire toute remarque sur ce créneau d'intervention le plus
|
||||
tôt possible.
|
||||
|
@ -240,7 +240,7 @@ main() {
|
|||
echo "MySQL" >>"${servicesToRestart}"
|
||||
elif echo "${pkg}" | grep -q "^mariadb-server"; then
|
||||
echo "MariaDB" >>"${servicesToRestart}"
|
||||
elif echo "${pkg}" | grep -qE "^postgresql-[[:digit:]]+\.[[:digit:]]+$"; then
|
||||
elif echo "${pkg}" | grep -qE "^postgresql-[[:digit:]]+(\.[[:digit:]]+)?$"; then
|
||||
echo "PostgreSQL" >>"${servicesToRestart}"
|
||||
elif echo "${pkg}" | grep -qE "^tomcat[[:digit:]]+$"; then
|
||||
echo "Tomcat" >>"${servicesToRestart}"
|
||||
|
|
|
@ -8,3 +8,5 @@ logstash_custom_tmpdir: Null
|
|||
logstash_default_tmpdir: /var/lib/logstash/tmp
|
||||
logstash_log_syslog_enabled: True
|
||||
logstash_config_force: True
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -29,7 +29,7 @@
|
|||
- name: Elastic GPG key is installed
|
||||
copy:
|
||||
src: elastic.asc
|
||||
dest: /etc/apt/trusted.gpg.d/elastic.asc
|
||||
dest: "{{ apt_keyring_dir }}/elastic.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
|
@ -40,7 +40,7 @@
|
|||
|
||||
- name: Elastic sources list is available
|
||||
apt_repository:
|
||||
repo: "deb https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
repo: "deb [signed-by={{ apt_keyring_dir }}/elastic.asc] https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
filename: elastic
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
@ -48,6 +48,16 @@
|
|||
- logstash
|
||||
- packages
|
||||
|
||||
- name: Unsigned Elastic sources list is not available
|
||||
apt_repository:
|
||||
repo: "deb https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
filename: elastic
|
||||
state: absent
|
||||
update_cache: yes
|
||||
tags:
|
||||
- logstash
|
||||
- packages
|
||||
|
||||
- name: Logstash is installed
|
||||
apt:
|
||||
name: logstash
|
||||
|
|
|
@ -21,3 +21,13 @@ lxc_php_container_releases:
|
|||
php74: "bullseye"
|
||||
php80: "bullseye"
|
||||
php81: "bullseye"
|
||||
|
||||
lxc_php_services:
|
||||
php56: 'php5-fpm.service'
|
||||
php70: 'php7.0-fpm.service'
|
||||
php73: 'php7.3-fpm.service'
|
||||
php74: 'php7.4-fpm.service'
|
||||
php80: 'php8.0-fpm.service'
|
||||
php81: 'php8.1-fpm.service'
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -1,4 +1,15 @@
|
|||
---
|
||||
|
||||
- name: Reload PHP-FPM
|
||||
lxc_container:
|
||||
name: "{{ lxc_php_version }}"
|
||||
container_command: "systemctl reload {{ lxc_php_services[lxc_php_version] }}"
|
||||
|
||||
- name: Restart PHP-FPM
|
||||
lxc_container:
|
||||
name: "{{ lxc_php_version }}"
|
||||
container_command: "systemctl restart {{ lxc_php_services[lxc_php_version] }}"
|
||||
|
||||
- name: Reload php81-fpm
|
||||
lxc_container:
|
||||
name: "{{ lxc_php_version }}"
|
||||
|
@ -34,6 +45,11 @@
|
|||
name: "{{ lxc_php_version }}"
|
||||
container_command: "systemctl restart opensmtpd"
|
||||
|
||||
- name: Daemon reload
|
||||
lxc_container:
|
||||
name: "{{ lxc_php_version }}"
|
||||
container_command: "systemctl daemon-reload"
|
||||
|
||||
- name: Restart container
|
||||
lxc_container:
|
||||
name: "{{ lxc_php_version }}"
|
||||
|
|
|
@ -27,4 +27,6 @@
|
|||
- include: "php81.yml"
|
||||
when: lxc_php_version == "php81"
|
||||
|
||||
- include: "umask.yml"
|
||||
|
||||
- include: "misc.yml"
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
create: yes
|
||||
mode: "0644"
|
||||
loop:
|
||||
- "deb https://packages.sury.org/php/ bullseye main"
|
||||
- "deb http://pub.evolix.net/ bullseye-php80/"
|
||||
- "deb [signed-by={{ apt_keyring_dir }}/sury.gpg] https://packages.sury.org/php/ bullseye main"
|
||||
- "deb [signed-by={{ apt_keyring_dir }}/reg.asc] http://pub.evolix.net/ bullseye-php80/"
|
||||
|
||||
- name: copy pub.evolix.net GPG key
|
||||
copy:
|
||||
src: reg.asc
|
||||
dest: /var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/apt/trusted.gpg.d/reg.asc
|
||||
dest: /var/lib/lxc/{{ lxc_php_version }}/rootfs{{ apt_keyring_dir }}/reg.asc
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
|
@ -33,7 +33,7 @@
|
|||
- name: copy packages.sury.org GPG Key
|
||||
copy:
|
||||
src: sury.gpg
|
||||
dest: /var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/apt/trusted.gpg.d/sury.gpg
|
||||
dest: /var/lib/lxc/{{ lxc_php_version }}/rootfs{{ apt_keyring_dir }}/sury.gpg
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
create: yes
|
||||
mode: "0644"
|
||||
loop:
|
||||
- "deb https://packages.sury.org/php/ bullseye main"
|
||||
- "deb http://pub.evolix.net/ bullseye-php81/"
|
||||
- "deb [signed-by={{ apt_keyring_dir }}/sury.gpg] https://packages.sury.org/php/ bullseye main"
|
||||
- "deb [signed-by={{ apt_keyring_dir }}/reg.asc] http://pub.evolix.net/ bullseye-php81/"
|
||||
|
||||
- name: copy pub.evolix.net GPG key
|
||||
copy:
|
||||
src: reg.asc
|
||||
dest: /var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/apt/trusted.gpg.d/reg.asc
|
||||
dest: /var/lib/lxc/{{ lxc_php_version }}/rootfs{{ apt_keyring_dir }}/reg.asc
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
|
@ -33,7 +33,7 @@
|
|||
- name: copy packages.sury.org GPG Key
|
||||
copy:
|
||||
src: sury.gpg
|
||||
dest: /var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/apt/trusted.gpg.d/sury.gpg
|
||||
dest: /var/lib/lxc/{{ lxc_php_version }}/rootfs{{ apt_keyring_dir }}/sury.gpg
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
|
|
32
lxc-php/tasks/umask.yml
Normal file
32
lxc-php/tasks/umask.yml
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Ajoute UMask=0007 à l'unité systemd PHP-FPM du conteneur LXC
|
||||
# dans /etc/systemd/system/phpX.X-fpm.service.d/evolinux.conf
|
||||
---
|
||||
|
||||
- name: "Définis le chemin du système de fichiers du conteneur LXC."
|
||||
set_fact:
|
||||
lxc_rootfs_path: "/var/lib/lxc/{{ lxc_php_version }}/rootfs"
|
||||
|
||||
- name: "Crée des répertoires (si absents) pour surcharger la config des services PHP dans les conteneurs LXC."
|
||||
ansible.builtin.file:
|
||||
path: "{{ lxc_rootfs_path }}/etc/systemd/system/{{ lxc_php_services[lxc_php_version] }}.d"
|
||||
state: directory
|
||||
register: systemd_path
|
||||
|
||||
- name: "[Service] est présent dans la surchage des services PHP-FPM des conteneurs LXC."
|
||||
ansible.builtin.lineinfile:
|
||||
path: "{{ systemd_path.path }}/evolinux.conf"
|
||||
regex: "\\[Service\\]"
|
||||
line: "[Service]"
|
||||
create: yes
|
||||
|
||||
- name: "UMask=0007 est présent dans la surchage des services PHP-FPM des conteneurs LXC."
|
||||
ansible.builtin.lineinfile:
|
||||
path: "{{ systemd_path.path }}/evolinux.conf"
|
||||
regex: "^UMask="
|
||||
line: "UMask=0007"
|
||||
insertafter: "\\[Service\\]"
|
||||
when: not ansible_check_mode
|
||||
notify:
|
||||
- "Daemon reload"
|
||||
- "Restart PHP-FPM"
|
||||
|
|
@ -14,5 +14,9 @@
|
|||
# release: stretch
|
||||
# solr_version: 8.4.1
|
||||
# solr_port: 8985
|
||||
# - name: solr9
|
||||
# release: bullseye
|
||||
# solr_version: 9.0.0
|
||||
# solr_port: 8985
|
||||
lxc_containers: []
|
||||
|
||||
|
|
|
@ -10,5 +10,9 @@
|
|||
mode: '0755'
|
||||
loop: "{{ lxc_containers }}"
|
||||
|
||||
- include: "solr.yml name={{item.name}} solr_version={{item.solr_version}} solr_port={{item.solr_port}}"
|
||||
- include: solr.yml
|
||||
args:
|
||||
name: "{{ item.name }}"
|
||||
solr_version: "{{ item.solr_version }}"
|
||||
solr_port: "{{ item.solr_port }}"
|
||||
loop: "{{ lxc_containers }}"
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
---
|
||||
- name: Install openjdk-8-jre-headless and lsof packages
|
||||
command: "lxc-attach -n {{name}} -- apt-get install -y openjdk-8-jre-headless lsof"
|
||||
|
||||
- name: "Set values for Solr < 9.0.0"
|
||||
set_fact:
|
||||
tarball_url: https://archive.apache.org/dist/lucene/solr/{{ solr_version }}/solr-{{ solr_version }}.tgz
|
||||
tarball_path: /var/lib/lxc/{{ name }}/rootfs/root/solr-{{ solr_version }}.tgz
|
||||
start_command: "/etc/init.d/solr start"
|
||||
stop_command: "/etc/init.d/solr stop"
|
||||
when: "solr_version is version('9.0.0', '<')"
|
||||
|
||||
- name: "Set values for Solr >= 9.0.0"
|
||||
set_fact:
|
||||
tarball_url: https://archive.apache.org/dist/solr/solr/{{ solr_version }}/solr-{{ solr_version }}.tgz
|
||||
tarball_path: /var/lib/lxc/{{ name }}/rootfs/root/solr-{{ solr_version }}.tgz
|
||||
start_command: "systemctl start solr"
|
||||
stop_command: "systemctl stop solr"
|
||||
when: "solr_version is version('9.0.0', '>=')"
|
||||
|
||||
- name: Install java and lsof packages
|
||||
command: "lxc-attach -n {{ name }} -- apt-get install -y default-jre-headless lsof"
|
||||
|
||||
- name: "Download Solr {{ solr_version }}"
|
||||
get_url:
|
||||
url: "https://archive.apache.org/dist/lucene/solr/{{ solr_version }}/solr-{{ solr_version }}.tgz"
|
||||
dest: "/var/lib/lxc/{{ name }}/rootfs/root/solr-{{ solr_version }}.tgz"
|
||||
url: "{{ tarball_url }}"
|
||||
dest: "{{ tarball_path }}"
|
||||
mode: '0644'
|
||||
|
||||
- name: "Extract solr-{{ solr_version }}.tgz"
|
||||
unarchive:
|
||||
src: /var/lib/lxc/{{ name }}/rootfs/root/solr-{{ solr_version }}.tgz
|
||||
src: "{{ tarball_path }}"
|
||||
dest: /var/lib/lxc/{{ name }}/rootfs/root/
|
||||
remote_src: yes
|
||||
|
||||
- name: "Install Solr {{ solr_version }}"
|
||||
command: "lxc-attach -n {{name}} -- /root/solr-{{ solr_version }}/bin/install_solr_service.sh /root/solr-{{ solr_version }}.tgz"
|
||||
|
||||
- name: "Stop Solr"
|
||||
command: "lxc-attach -n {{name}} -- /etc/init.d/solr stop"
|
||||
ignore_errors: True
|
||||
|
||||
- name: "Make sure /home/solr exists"
|
||||
file:
|
||||
path: /home/solr
|
||||
path: /home/solr/{{ name }}
|
||||
recurse: yes
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: "Move Solr data directory to /home/solr/{{name}}"
|
||||
command: "lxc-attach -n {{name}} -- mv /var/solr /home/solr/{{name}}"
|
||||
|
||||
- name: "Create a symbolic link to /home/solr/{{name}}"
|
||||
command: "lxc-attach -n {{name}} -- ln -s /home/solr/{{name}} /var/solr"
|
||||
|
||||
- name: "Set Solr port to {{ solr_port }}"
|
||||
lineinfile:
|
||||
dest: /var/lib/lxc/{{ name }}/rootfs/etc/default/solr.in.sh
|
||||
line: "SOLR_PORT={{ solr_port }}"
|
||||
|
||||
- name: "Start Solr"
|
||||
command: "lxc-attach -n {{name}} -- /etc/init.d/solr start"
|
||||
- name: "Install Solr {{ solr_version }}"
|
||||
command: "lxc-attach -n {{name}} -- /root/solr-{{ solr_version }}/bin/install_solr_service.sh /root/solr-{{ solr_version }}.tgz -d /home/solr/{{name}} -p {{ solr_port }}"
|
||||
|
|
|
@ -15,4 +15,6 @@ lxc_mount_part: "/home"
|
|||
# release: jessie
|
||||
# - name: php70
|
||||
# release: stretch
|
||||
# - name: php81
|
||||
# release: bullseye
|
||||
lxc_containers: []
|
||||
|
|
|
@ -43,11 +43,19 @@
|
|||
- lxc_unprivilegied_containers | bool
|
||||
- root_subuids.rc != 0
|
||||
|
||||
- name: Check if /var has not mount options or nosuid or nodev or noexec
|
||||
shell: findmnt | grep -E "/var[^/]" | grep -e nodev -e noexec -e nosuid
|
||||
register: check_var
|
||||
- name: Get filesystem options
|
||||
command: findmnt --noheadings --target /var/lib/lxc --output OPTIONS
|
||||
changed_when: false
|
||||
failed_when: "check_var.rc == 0"
|
||||
check_mode: no
|
||||
register: check_fs_options
|
||||
|
||||
- name: Check if options are correct
|
||||
assert:
|
||||
that:
|
||||
- "'nodev' not in check_fs_options.stdout"
|
||||
- "'noexec' not in check_fs_options.stdout"
|
||||
- "'nosuid' not in check_fs_options.stdout"
|
||||
msg: "LXC directory is in a filesystem with incompatible options"
|
||||
|
||||
- name: Create containers
|
||||
include: create-container.yml
|
||||
|
|
|
@ -28,3 +28,5 @@ metricbeat_tags: Null
|
|||
# metricbeat_fields:
|
||||
# - "env: staging"
|
||||
metricbeat_fields: Null
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -29,7 +29,7 @@
|
|||
- name: Elastic GPG key is installed
|
||||
copy:
|
||||
src: elastic.asc
|
||||
dest: /etc/apt/trusted.gpg.d/elastic.asc
|
||||
dest: "{{ apt_keyring_dir }}/elastic.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
|
@ -40,7 +40,7 @@
|
|||
|
||||
- name: Elastic sources list is available
|
||||
apt_repository:
|
||||
repo: "deb https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
repo: "deb [signed-by={{ apt_keyring_dir }}/elastic.asc] https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
filename: elastic
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
@ -48,6 +48,16 @@
|
|||
- metricbeat
|
||||
- packages
|
||||
|
||||
- name: Elastic sources list is available
|
||||
apt_repository:
|
||||
repo: "deb https://artifacts.elastic.co/packages/{{ elastic_stack_version | mandatory }}/apt stable main"
|
||||
filename: elastic
|
||||
state: absent
|
||||
update_cache: yes
|
||||
tags:
|
||||
- metricbeat
|
||||
- packages
|
||||
|
||||
- name: Metricbeat is installed
|
||||
apt:
|
||||
name: metricbeat
|
||||
|
|
|
@ -55,7 +55,7 @@ DNSSERVEURS='0.0.0.0/0'
|
|||
# HTTP authorizations
|
||||
# (you can use DNS names but set cron to reload minifirewall regularly)
|
||||
# (if you have HTTP proxy, set 0.0.0.0/0)
|
||||
# HTTPSITES='security.debian.org pub.evolix.net security-cdn.debian.org mirror.evolix.org backports.debian.org hwraid.le-vert.net antispam00.evolix.org spamassassin.apache.org sa-update.space-pro.be sa-update.secnap.net www.sa-update.pccc.com sa-update.dnswl.org ocsp.int-x3.letsencrypt.org'
|
||||
# HTTPSITES='security.debian.org pub.evolix.net security-cdn.debian.org mirror.evolix.org backports.debian.org hwraid.le-vert.net antispam00.evolix.org spamassassin.apache.org sa-update.space-pro.be sa-update.secnap.net www.sa-update.pccc.com sa-update.dnswl.org ocsp.int-x3.letsencrypt.org deb.freexian.com'
|
||||
HTTPSITES='0.0.0.0/0'
|
||||
|
||||
# HTTPS authorizations
|
||||
|
|
|
@ -8,3 +8,5 @@ mongodb_bind: 127.0.0.1
|
|||
mongodb_force_config: False
|
||||
|
||||
mongodb_version: 4.4
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -4,8 +4,12 @@
|
|||
msg: Not compatible with Debian 11 (Bullseye)
|
||||
when:
|
||||
- ansible_distribution_release == "bullseye"
|
||||
- mongodb_version is version('5.0', '<=')
|
||||
- mongodb_version is version('5.0', '<')
|
||||
|
||||
- name: Look for legacy apt keyring
|
||||
stat:
|
||||
path: /etc/apt/trusted.gpg
|
||||
register: _trusted_gpg_keyring
|
||||
|
||||
- name: MongoDB embedded GPG key is absent
|
||||
apt_key:
|
||||
|
@ -17,19 +21,26 @@
|
|||
- name: Add MongoDB GPG key
|
||||
copy:
|
||||
src: "server-{{mongodb_version}}.asc"
|
||||
dest: "/etc/apt/trusted.gpg.d/mongodb-server-{{mongodb_version}}.asc"
|
||||
dest: "{{ apt_keyring_dir }}/mongodb-server-{{mongodb_version}}.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: enable APT sources list
|
||||
- name: Enable APT sources list
|
||||
apt_repository:
|
||||
repo: "deb http://repo.mongodb.org/apt/debian buster/mongodb-org/{{mongodb_version}} main"
|
||||
repo: "deb [signed-by={{ apt_keyring_dir }}/mongodb-server-{{mongodb_version}}.asc] http://repo.mongodb.org/apt/debian bullseye/mongodb-org/{{mongodb_version}} main"
|
||||
state: present
|
||||
filename: "mongodb-org-{{mongodb_version}}"
|
||||
update_cache: yes
|
||||
|
||||
- name: Disable unsigned APT sources list
|
||||
apt_repository:
|
||||
repo: "deb http://repo.mongodb.org/apt/debian bullseye/mongodb-org/{{mongodb_version}} main"
|
||||
state: absent
|
||||
filename: "mongodb-org-{{mongodb_version}}"
|
||||
update_cache: yes
|
||||
|
||||
- name: Install packages
|
||||
apt:
|
||||
name: mongodb-org
|
||||
|
@ -46,19 +57,19 @@
|
|||
|
||||
- name: install dependency for monitoring
|
||||
apt:
|
||||
name: python-pymongo
|
||||
name: python3-pymongo
|
||||
state: present
|
||||
|
||||
- name: Custom configuration
|
||||
template:
|
||||
src: mongodb_buster.conf.j2
|
||||
src: mongodb_bullseye.conf.j2
|
||||
dest: "/etc/mongod.conf"
|
||||
force: "{{ mongodb_force_config | bool | ternary('yes', 'no') }}"
|
||||
notify: restart mongod
|
||||
|
||||
- name: Configure logrotate
|
||||
template:
|
||||
src: logrotate_buster.j2
|
||||
src: logrotate_bullseye.j2
|
||||
dest: /etc/logrotate.d/mongodb
|
||||
force: yes
|
||||
backup: no
|
||||
|
|
|
@ -15,19 +15,26 @@
|
|||
- name: Add MongoDB GPG key
|
||||
copy:
|
||||
src: "server-{{mongodb_version}}.asc"
|
||||
dest: "/etc/apt/trusted.gpg.d/mongodb-server-{{mongodb_version}}.asc"
|
||||
dest: "{{ apt_keyring_dir }}/mongodb-server-{{ mongodb_version }}.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: enable APT sources list
|
||||
- name: Enable APT sources list
|
||||
apt_repository:
|
||||
repo: "deb http://repo.mongodb.org/apt/debian buster/mongodb-org/{{mongodb_version}} main"
|
||||
repo: "deb [signed-by={{ apt_keyring_dir }}/mongodb-server-{{ mongodb_version }}.asc] http://repo.mongodb.org/apt/debian buster/mongodb-org/{{ mongodb_version }} main"
|
||||
state: present
|
||||
filename: "mongodb-org-{{mongodb_version}}"
|
||||
update_cache: yes
|
||||
|
||||
- name: Disable unsigned APT sources list
|
||||
apt_repository:
|
||||
repo: "deb http://repo.mongodb.org/apt/debian buster/mongodb-org/{{ mongodb_version }} main"
|
||||
state: absent
|
||||
filename: "mongodb-org-{{mongodb_version}}"
|
||||
update_cache: yes
|
||||
|
||||
- name: Install packages
|
||||
apt:
|
||||
name: mongodb-org
|
||||
|
|
|
@ -1,15 +1,38 @@
|
|||
---
|
||||
|
||||
- name: MongoDB public GPG Key
|
||||
apt_key:
|
||||
# url: https://www.mongodb.org/static/pgp/server-3.4.asc
|
||||
data: "{{ lookup('file', 'server-3.4.asc') }}"
|
||||
- name: Look for legacy apt keyring
|
||||
stat:
|
||||
path: /etc/apt/trusted.gpg
|
||||
register: _trusted_gpg_keyring
|
||||
|
||||
- name: enable APT sources list
|
||||
- name: MongoDB embedded GPG key is absent
|
||||
apt_key:
|
||||
id: "B8612B5D"
|
||||
keyring: /etc/apt/trusted.gpg
|
||||
state: absent
|
||||
when: _trusted_gpg_keyring.stat.exists
|
||||
|
||||
- name: Add MongoDB GPG key
|
||||
copy:
|
||||
src: "server-{{mongodb_version}}.asc"
|
||||
dest: "/etc/apt/trusted.gpg.d/mongodb-server-{{mongodb_version}}.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: Enable APT sources list
|
||||
apt_repository:
|
||||
repo: deb http://repo.mongodb.org/apt/debian jessie/mongodb-org/3.4 main
|
||||
repo: "deb http://repo.mongodb.org/apt/debian jessie/mongodb-org/{{mongodb_version}} main"
|
||||
state: present
|
||||
filename: mongodb
|
||||
filename: "mongodb-org-{{mongodb_version}}"
|
||||
update_cache: yes
|
||||
|
||||
- name: Disable APT sources list
|
||||
apt_repository:
|
||||
repo: "deb http://repo.mongodb.org/apt/debian jessie/mongodb-org/{{mongodb_version}} main"
|
||||
state: absent
|
||||
filename: "mongodb-org-{{mongodb_version}}"
|
||||
update_cache: yes
|
||||
|
||||
- name: Install packages
|
||||
|
|
|
@ -4,44 +4,44 @@
|
|||
set_fact:
|
||||
mysql_restart_handler_name: "{{ mysql_restart_if_needed | bool | ternary('restart mysql', 'restart mysql (noop)') }}"
|
||||
|
||||
- include: packages_stretch.yml
|
||||
- include_tasks: packages_stretch.yml
|
||||
when: ansible_distribution_major_version is version('9', '>=')
|
||||
|
||||
- include: packages_jessie.yml
|
||||
- include_tasks: packages_jessie.yml
|
||||
when: ansible_distribution_release == "jessie"
|
||||
|
||||
## There is nothing to do with users on Debian 11 - yet we need a /root/.my.cnf for compatibility
|
||||
- include: users_bullseye.yml
|
||||
when: ansible_distribution_release == "bullseye"
|
||||
## There is nothing to do with users on Debian 11+ - yet we need a /root/.my.cnf for compatibility
|
||||
- include_tasks: users_bullseye.yml
|
||||
when: ansible_distribution_major_version is version('11', '>=')
|
||||
|
||||
- include: users_buster.yml
|
||||
- include_tasks: users_buster.yml
|
||||
when: ansible_distribution_release == "buster"
|
||||
|
||||
- include: users_stretch.yml
|
||||
- include_tasks: users_stretch.yml
|
||||
when: ansible_distribution_release == "stretch"
|
||||
|
||||
- include: users_jessie.yml
|
||||
- include_tasks: users_jessie.yml
|
||||
when: ansible_distribution_release == "jessie"
|
||||
|
||||
- include: config_stretch.yml
|
||||
- include_tasks: config_stretch.yml
|
||||
when: ansible_distribution_major_version is version('9', '>=')
|
||||
|
||||
- include: config_jessie.yml
|
||||
- include_tasks: config_jessie.yml
|
||||
when: ansible_distribution_release == "jessie"
|
||||
|
||||
- include: replication.yml
|
||||
- include_tasks: replication.yml
|
||||
when: mysql_replication | bool
|
||||
|
||||
- include: datadir.yml
|
||||
- include_tasks: datadir.yml
|
||||
|
||||
- include: logdir.yml
|
||||
- include_tasks: logdir.yml
|
||||
|
||||
- include: tmpdir.yml
|
||||
- include_tasks: tmpdir.yml
|
||||
|
||||
- include: nrpe.yml
|
||||
- include_tasks: nrpe.yml
|
||||
|
||||
- include: munin.yml
|
||||
- include_tasks: munin.yml
|
||||
|
||||
- include: log2mail.yml
|
||||
- include_tasks: log2mail.yml
|
||||
|
||||
- include: utils.yml
|
||||
- include_tasks: utils.yml
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
# mytop
|
||||
|
||||
- name: "Install mytop (Debian 9)"
|
||||
- name: "Install mytop (Debian 8)"
|
||||
apt:
|
||||
name: mytop
|
||||
state: present
|
||||
|
@ -43,14 +43,23 @@
|
|||
- libterm-readkey-perl
|
||||
when: ansible_distribution_release == "buster"
|
||||
|
||||
- name: "Install dependencies for mytop (Debian 11 or later)"
|
||||
- name: "Install dependencies for mytop (Debian 11)"
|
||||
apt:
|
||||
name:
|
||||
- mariadb-client-10.5
|
||||
- libconfig-inifiles-perl
|
||||
- libterm-readkey-perl
|
||||
- libdbd-mariadb-perl
|
||||
when: ansible_distribution_major_version is version('11', '>=')
|
||||
when: ansible_distribution_release == "bullseye"
|
||||
|
||||
- name: "Install dependencies for mytop (Debian 12 or later)"
|
||||
apt:
|
||||
name:
|
||||
- mariadb-client-10.6
|
||||
- libconfig-inifiles-perl
|
||||
- libterm-readkey-perl
|
||||
- libdbd-mariadb-perl
|
||||
when: ansible_distribution_major_version is version('12', '=')
|
||||
|
||||
- name: Read debian-sys-maint password (Debian < 11)
|
||||
shell: 'cat /etc/mysql/debian.cnf | grep -m1 "password = .*" | cut -d" " -f3'
|
||||
|
|
232
nagios-nrpe/files/plugins/check_ceph_df
Executable file
232
nagios-nrpe/files/plugins/check_ceph_df
Executable file
|
@ -0,0 +1,232 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2013 SWITCH http://www.switch.ch
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
__version__ = '1.7.1'
|
||||
|
||||
# default ceph values
|
||||
CEPH_COMMAND = '/usr/bin/ceph'
|
||||
|
||||
# nagios exit code
|
||||
STATUS_OK = 0
|
||||
STATUS_WARNING = 1
|
||||
STATUS_ERROR = 2
|
||||
STATUS_UNKNOWN = 3
|
||||
|
||||
def main():
|
||||
|
||||
# parse args
|
||||
parser = argparse.ArgumentParser(description="'ceph df' nagios plugin.")
|
||||
parser.add_argument('-e','--exe', help='ceph executable [%s]' % CEPH_COMMAND)
|
||||
parser.add_argument('-c','--conf', help='alternative ceph conf file')
|
||||
parser.add_argument('-m','--monaddress', help='ceph monitor address[:port]')
|
||||
parser.add_argument('-i','--id', help='ceph client id')
|
||||
parser.add_argument('-n','--name', help='ceph client name')
|
||||
parser.add_argument('-k','--keyring', help='ceph client keyring file')
|
||||
parser.add_argument('-p','--pool', help='ceph pool name')
|
||||
parser.add_argument('-d','--detail', help="show pool details on warn and critical", action='store_true')
|
||||
parser.add_argument('-W','--warn', help="warn above this percent RAW USED", type=float)
|
||||
parser.add_argument('-C','--critical', help="critical alert above this percent RAW USED", type=float)
|
||||
parser.add_argument('-V','--version', help='show version and exit', action='store_true')
|
||||
args = parser.parse_args()
|
||||
|
||||
# validate args
|
||||
ceph_exec = args.exe if args.exe else CEPH_COMMAND
|
||||
if not os.path.exists(ceph_exec):
|
||||
print("ERROR: ceph executable '%s' doesn't exist" % ceph_exec)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.version:
|
||||
print('version %s' % __version__)
|
||||
return STATUS_OK
|
||||
|
||||
if args.conf and not os.path.exists(args.conf):
|
||||
print("ERROR: ceph conf file '%s' doesn't exist" % args.conf)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.keyring and not os.path.exists(args.keyring):
|
||||
print("ERROR: keyring file '%s' doesn't exist" % args.keyring)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if not args.warn or not args.critical or args.warn > args.critical:
|
||||
print("ERROR: warn and critical level must be set and critical must be greater than warn")
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
# build command
|
||||
ceph_df = [ceph_exec]
|
||||
if args.monaddress:
|
||||
ceph_df.append('-m')
|
||||
ceph_df.append(args.monaddress)
|
||||
if args.conf:
|
||||
ceph_df.append('-c')
|
||||
ceph_df.append(args.conf)
|
||||
if args.id:
|
||||
ceph_df.append('--id')
|
||||
ceph_df.append(args.id)
|
||||
if args.name:
|
||||
ceph_df.append('--name')
|
||||
ceph_df.append(args.name)
|
||||
if args.keyring:
|
||||
ceph_df.append('--keyring')
|
||||
ceph_df.append(args.keyring)
|
||||
ceph_df.append('df')
|
||||
|
||||
#print ceph_df
|
||||
|
||||
# exec command
|
||||
p = subprocess.Popen(ceph_df,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
||||
output, err = p.communicate()
|
||||
|
||||
# parse output
|
||||
# print "DEBUG: output:", output
|
||||
# print "DEBUG: err:", err
|
||||
if output:
|
||||
output = output.decode('utf-8')
|
||||
# parse output
|
||||
# if detail switch was not set only show global values and compare to warning and critical
|
||||
# otherwise show space for pools too
|
||||
result=output.splitlines()
|
||||
# values for GLOBAL are in 3rd line of output
|
||||
globalline = result[2]
|
||||
globalvals = globalline.split()
|
||||
# Luminous vs Minic output (27.3TiB vs 27.3 TiB)
|
||||
if len(globalvals) == 7:
|
||||
gv = []
|
||||
gv.append("{}{}".format(globalvals[0], globalvals[1]))
|
||||
gv.append("{}{}".format(globalvals[2], globalvals[3]))
|
||||
gv.append("{}{}".format(globalvals[4], globalvals[5]))
|
||||
gv.append(globalvals[6])
|
||||
globalvals = gv
|
||||
#print "XXX: globalvals: {} {}".format(len(globalvals), globalvals)
|
||||
# Nautilus output
|
||||
if len(globalvals) == 10:
|
||||
gv = []
|
||||
gv.append("{}{}".format(globalvals[1], globalvals[2]))
|
||||
gv.append("{}{}".format(globalvals[3], globalvals[4]))
|
||||
gv.append("{}{}".format(globalvals[5], globalvals[6]))
|
||||
gv.append(globalvals[9])
|
||||
globalvals = gv
|
||||
#print "XXX: globalvals: {} {}".format(len(globalvals), globalvals)
|
||||
|
||||
# prepare pool values
|
||||
# pool output starts in line 4 with the bare word POOLS: followed by the output
|
||||
poollines = result[3:]
|
||||
|
||||
if args.pool:
|
||||
for line in poollines:
|
||||
if args.pool in line:
|
||||
poolvals = line.split()
|
||||
# Luminous vs Minic output (27.3TiB vs 27.3 TiB)
|
||||
if len(poolvals) == 8:
|
||||
pv = []
|
||||
pv.append(poolvals[0]) # NAME
|
||||
pv.append(poolvals[1]) # ID
|
||||
pv.append("{}{}".format(poolvals[2], poolvals[3])) # USED 27.3 TiB
|
||||
pv.append(poolvals[4]) # %USED
|
||||
pv.append("{}{}".format(poolvals[5], poolvals[6])) # MAX AVAIL 27.3 TiB
|
||||
# pv.append(poolvals[7]) # OBJECTS
|
||||
poolvals = pv
|
||||
#print "XXX: poolvals: {} {}".format(len(poolvals), poolvals)
|
||||
# Nautilus output
|
||||
if len(poolvals) == 10:
|
||||
pv = []
|
||||
pv.append(poolvals[0]) # NAME
|
||||
pv.append(poolvals[1]) # ID
|
||||
pv.append("{}{}".format(poolvals[2], poolvals[3])) # USED 27.3 TiB
|
||||
pv.append(poolvals[7]) # %USED
|
||||
pv.append("{}{}".format(poolvals[8], poolvals[9])) # MAX AVAIL 27.3 TiB
|
||||
# pv.append(poolvals[7]) # OBJECTS, not used
|
||||
poolvals = pv
|
||||
#print "XXX: poolvals: {} {}".format(len(poolvals), poolvals)
|
||||
# Octopus >= v15.2.8 (pgs added to ceph-df)
|
||||
if len(poolvals) == 11:
|
||||
pv = []
|
||||
pv.append(poolvals[0]) # NAME
|
||||
pv.append(poolvals[1]) # ID
|
||||
#pv.append(poolvals[2]) # PGS, not used
|
||||
pv.append("{}{}".format(poolvals[3], poolvals[4])) # USED 27.3 TiB
|
||||
pv.append(poolvals[8]) # %USED
|
||||
pv.append("{}{}".format(poolvals[9], poolvals[10])) # MAX AVAIL 27.3 TiB
|
||||
# pv.append(poolvals[7]) # OBJECTS, not used
|
||||
poolvals = pv
|
||||
#print "XXX: poolvals: {} {}".format(len(poolvals), poolvals)
|
||||
|
||||
|
||||
pool_used = poolvals[2]
|
||||
pool_usage_percent = float(poolvals[3])
|
||||
pool_available_space = poolvals[4]
|
||||
# pool_objects = float(poolvals[5]) # not used
|
||||
|
||||
if pool_usage_percent > args.critical:
|
||||
print('CRITICAL: %s%% usage in Pool \'%s\' is above %s%% (%s used) | Usage=%s%%;%s;%s;;' % (pool_usage_percent, args.pool, args.critical, pool_used, pool_usage_percent, args.warn, args.critical))
|
||||
return STATUS_ERROR
|
||||
if pool_usage_percent > args.warn:
|
||||
print('WARNING: %s%% usage in Pool \'%s\' is above %s%% (%s used) | Usage=%s%%;%s;%s;;' % (pool_usage_percent, args.pool, args.warn, pool_used, pool_usage_percent, args.warn, args.critical))
|
||||
return STATUS_WARNING
|
||||
else:
|
||||
print('%s%% usage in Pool \'%s\' | Usage=%s%%;%s;%s;;' % (pool_usage_percent, args.pool, pool_usage_percent, args.warn, args.critical))
|
||||
return STATUS_OK
|
||||
else:
|
||||
# print 'DEBUG:', globalvals
|
||||
# finally 4th element contains percentual value
|
||||
# print 'DEBUG USAGE:', globalvals[3]
|
||||
global_usage_percent = float(globalvals[3])
|
||||
global_available_space = globalvals[1]
|
||||
global_total_space = globalvals[0]
|
||||
# print 'DEBUG WARNLEVEL:', args.warn
|
||||
# print 'DEBUG CRITICALLEVEL:', args.critical
|
||||
if global_usage_percent > args.critical:
|
||||
if args.detail:
|
||||
poollines.insert(0, '\n')
|
||||
poolout = '\n '.join(poollines)
|
||||
else:
|
||||
poolout = ''
|
||||
print('CRITICAL: global RAW usage of %s%% is above %s%% (%s of %s free)%s | Usage=%s%%;%s;%s;;' % (global_usage_percent, args.critical, global_available_space, global_total_space, poolout, global_usage_percent, args.warn, args.critical))
|
||||
return STATUS_ERROR
|
||||
elif global_usage_percent > args.warn:
|
||||
if args.detail:
|
||||
poollines.insert(0, '\n')
|
||||
poolout = '\n '.join(poollines)
|
||||
else:
|
||||
poolout = ''
|
||||
print('WARNING: global RAW usage of %s%% is above %s%% (%s of %s free)%s | Usage=%s%%;%s;%s;;' % (global_usage_percent, args.warn, global_available_space, global_total_space, poolout, global_usage_percent, args.warn, args.critical))
|
||||
return STATUS_WARNING
|
||||
else:
|
||||
print('RAW usage %s%% | Usage=%s%%;%s;%s;;' % (global_usage_percent, global_usage_percent, args.warn, args.critical))
|
||||
return STATUS_OK
|
||||
|
||||
#for
|
||||
elif err:
|
||||
# read only first line of error
|
||||
one_line = err.split('\n')[0]
|
||||
if '-1 ' in one_line:
|
||||
idx = one_line.rfind('-1 ')
|
||||
print('ERROR: %s: %s' % (ceph_exec, one_line[idx+len('-1 '):]))
|
||||
else:
|
||||
print(one_line)
|
||||
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
200
nagios-nrpe/files/plugins/check_ceph_health
Executable file
200
nagios-nrpe/files/plugins/check_ceph_health
Executable file
|
@ -0,0 +1,200 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2013-2016 SWITCH http://www.switch.ch
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import re
|
||||
import json
|
||||
|
||||
__version__ = '1.7.0'
|
||||
|
||||
# default ceph values
|
||||
CEPH_ADM_COMMAND = '/usr/sbin/cephadm'
|
||||
CEPH_COMMAND = '/usr/bin/ceph'
|
||||
|
||||
# nagios exit code
|
||||
STATUS_OK = 0
|
||||
STATUS_WARNING = 1
|
||||
STATUS_ERROR = 2
|
||||
STATUS_UNKNOWN = 3
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
# parse args
|
||||
parser = argparse.ArgumentParser(description="'ceph health' nagios plugin.")
|
||||
parser.add_argument('-e','--exe', help='ceph executable [%s]' % CEPH_COMMAND)
|
||||
parser.add_argument('-A','--admexe', help='cephadm executable [%s]' % CEPH_ADM_COMMAND)
|
||||
parser.add_argument('--cluster', help='ceph cluster name')
|
||||
parser.add_argument('-c','--conf', help='alternative ceph conf file')
|
||||
parser.add_argument('-m','--monaddress', help='ceph monitor address[:port]')
|
||||
parser.add_argument('-i','--id', help='ceph client id')
|
||||
parser.add_argument('-n','--name', help='ceph client name')
|
||||
parser.add_argument('-k','--keyring', help='ceph client keyring file')
|
||||
parser.add_argument('--check', help='regexp of which check(s) to check (luminous+) '
|
||||
"Can be inverted, e.g. '^((?!(PG_DEGRADED|OBJECT_MISPLACED)$).)*$'")
|
||||
parser.add_argument('-w','--whitelist', help='whitelist regexp for ceph health warnings')
|
||||
parser.add_argument('-d','--detail', help="exec 'ceph health detail'", action='store_true')
|
||||
parser.add_argument('-V','--version', help='show version and exit', action='store_true')
|
||||
parser.add_argument('-a','--cephadm', help='uses cephadm to execute the command', action='store_true')
|
||||
parser.add_argument('-s','--skip-muted', help='skip muted checks', action='store_true')
|
||||
args = parser.parse_args()
|
||||
|
||||
# validate args
|
||||
cephadm_exec = args.admexe if args.admexe else CEPH_ADM_COMMAND
|
||||
ceph_exec = args.exe if args.exe else CEPH_COMMAND
|
||||
|
||||
if args.cephadm:
|
||||
if not os.path.exists(cephadm_exec):
|
||||
print("ERROR: cephadm executable '%s' doesn't exist" % cephadm_exec)
|
||||
return STATUS_UNKNOWN
|
||||
else:
|
||||
if not os.path.exists(ceph_exec):
|
||||
print("ERROR: ceph executable '%s' doesn't exist" % ceph_exec)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.version:
|
||||
print('version %s' % __version__)
|
||||
return STATUS_OK
|
||||
|
||||
if args.conf and not os.path.exists(args.conf):
|
||||
print("ERROR: ceph conf file '%s' doesn't exist" % args.conf)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.keyring and not os.path.exists(args.keyring):
|
||||
print("ERROR: keyring file '%s' doesn't exist" % args.keyring)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
# build command
|
||||
ceph_health = [ceph_exec]
|
||||
|
||||
if args.cephadm:
|
||||
# Prepend the command with the cephadm binary and the shell command
|
||||
ceph_health = [cephadm_exec, 'shell'] + ceph_health
|
||||
|
||||
if args.monaddress:
|
||||
ceph_health.append('-m')
|
||||
ceph_health.append(args.monaddress)
|
||||
if args.cluster:
|
||||
ceph_health.append('--cluster')
|
||||
ceph_health.append(args.cluster)
|
||||
if args.conf:
|
||||
ceph_health.append('-c')
|
||||
ceph_health.append(args.conf)
|
||||
if args.id:
|
||||
ceph_health.append('--id')
|
||||
ceph_health.append(args.id)
|
||||
if args.name:
|
||||
ceph_health.append('--name')
|
||||
ceph_health.append(args.name)
|
||||
if args.keyring:
|
||||
ceph_health.append('--keyring')
|
||||
ceph_health.append(args.keyring)
|
||||
ceph_health.append('health')
|
||||
if args.detail:
|
||||
ceph_health.append('detail')
|
||||
|
||||
ceph_health.append('--format')
|
||||
ceph_health.append('json')
|
||||
#print(ceph_health)
|
||||
|
||||
# exec command
|
||||
p = subprocess.Popen(ceph_health,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
||||
output, err = p.communicate()
|
||||
try:
|
||||
output = json.loads(output)
|
||||
except ValueError:
|
||||
output = dict()
|
||||
|
||||
# parse output
|
||||
# print "output:", output
|
||||
#print "err:", err
|
||||
if output:
|
||||
ret = STATUS_OK
|
||||
msg = ""
|
||||
extended = []
|
||||
if 'checks' in output:
|
||||
#luminous
|
||||
for check,status in output['checks'].items():
|
||||
# skip check if not selected
|
||||
if args.check and not re.search(args.check, check):
|
||||
continue
|
||||
|
||||
if args.skip_muted and ('muted' in status and status['muted']):
|
||||
continue
|
||||
|
||||
check_detail = "%s( %s )" % (check, status['summary']['message'])
|
||||
|
||||
if status["severity"] == "HEALTH_ERR":
|
||||
extended.append(msg)
|
||||
msg = "CRITICAL: %s" % check_detail
|
||||
ret = STATUS_ERROR
|
||||
continue
|
||||
|
||||
if args.whitelist and re.search(args.whitelist,status['summary']['message']):
|
||||
continue
|
||||
|
||||
check_msg = "WARNING: %s" % check_detail
|
||||
if not msg:
|
||||
msg = check_msg
|
||||
ret = STATUS_WARNING
|
||||
else:
|
||||
extended.append(check_msg)
|
||||
else:
|
||||
#pre-luminous
|
||||
for status in output["summary"]:
|
||||
if status != "HEALTH_OK":
|
||||
if status == "HEALTH_ERROR":
|
||||
msg = "CRITICAL: %s" % status['summary']
|
||||
ret = STATUS_ERROR
|
||||
continue
|
||||
|
||||
if args.whitelist and re.search(args.whitelist,status['summary']):
|
||||
continue
|
||||
|
||||
if not msg:
|
||||
msg = "WARNING: %s" % status['summary']
|
||||
ret = STATUS_WARNING
|
||||
else:
|
||||
extended.append("WARNING: %s" % status['summary'])
|
||||
|
||||
if msg:
|
||||
print(msg)
|
||||
else:
|
||||
print("HEALTH OK")
|
||||
if extended: print('\n'.join(extended))
|
||||
return ret
|
||||
|
||||
|
||||
elif err:
|
||||
# read only first line of error
|
||||
one_line = err.split('\n')[0]
|
||||
if '-1 ' in one_line:
|
||||
idx = one_line.rfind('-1 ')
|
||||
print('ERROR: %s: %s' % (ceph_exec, one_line[idx+len('-1 '):]))
|
||||
else:
|
||||
print(one_line)
|
||||
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
188
nagios-nrpe/files/plugins/check_ceph_mds
Executable file
188
nagios-nrpe/files/plugins/check_ceph_mds
Executable file
|
@ -0,0 +1,188 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2013 Catalyst IT http://www.catalyst.net.nz
|
||||
# Copyright (c) 2015 SWITCH http://www.switch.ch
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import socket
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import json
|
||||
|
||||
__version__ = '1.6.0'
|
||||
|
||||
# default ceph values
|
||||
CEPH_EXEC = '/usr/bin/ceph'
|
||||
CEPH_COMMAND = 'mds stat -f json'
|
||||
|
||||
# nagios exit code
|
||||
STATUS_OK = 0
|
||||
STATUS_WARNING = 1
|
||||
STATUS_ERROR = 2
|
||||
STATUS_UNKNOWN = 3
|
||||
|
||||
def main():
|
||||
# parse args
|
||||
parser = argparse.ArgumentParser(description="'ceph mds stat' nagios plugin.")
|
||||
parser.add_argument('-e','--exe', help='ceph executable [%s]' % CEPH_EXEC)
|
||||
parser.add_argument('-c','--conf', help='alternative ceph conf file')
|
||||
parser.add_argument('-m','--monaddress', help='ceph monitor to use for queries (address[:port])')
|
||||
parser.add_argument('-i','--id', help='ceph client id')
|
||||
parser.add_argument('-k','--keyring', help='ceph client keyring file')
|
||||
parser.add_argument('-V','--version', help='show version and exit', action='store_true')
|
||||
parser.add_argument('-n','--name', help='mds daemon name', required=True)
|
||||
parser.add_argument('-f','--filesystem', help='mds filesystem name', required=True)
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.version:
|
||||
print('version %s' % __version__)
|
||||
return STATUS_OK
|
||||
|
||||
# validate args
|
||||
ceph_exec = args.exe if args.exe else CEPH_EXEC
|
||||
if not os.path.exists(ceph_exec):
|
||||
print("MDS ERROR: ceph executable '%s' doesn't exist" % ceph_exec)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.conf and not os.path.exists(args.conf):
|
||||
print("MDS ERROR: ceph conf file '%s' doesn't exist" % args.conf)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.keyring and not os.path.exists(args.keyring):
|
||||
print("MDS ERROR: keyring file '%s' doesn't exist" % args.keyring)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
# build command
|
||||
ceph_cmd = [ceph_exec]
|
||||
if args.monaddress:
|
||||
ceph_cmd.append('-m')
|
||||
ceph_cmd.append(args.monaddress)
|
||||
if args.conf:
|
||||
ceph_cmd.append('-c')
|
||||
ceph_cmd.append(args.conf)
|
||||
if args.id:
|
||||
ceph_cmd.append('--id')
|
||||
ceph_cmd.append(args.id)
|
||||
if args.keyring:
|
||||
ceph_cmd.append('--keyring')
|
||||
ceph_cmd.append(args.keyring)
|
||||
ceph_cmd.extend(CEPH_COMMAND.split(' '))
|
||||
|
||||
# exec command
|
||||
p = subprocess.Popen(ceph_cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
||||
output, err = p.communicate()
|
||||
|
||||
if p.returncode != 0 or not output:
|
||||
print("MDS ERROR: %s" % err)
|
||||
return STATUS_ERROR
|
||||
|
||||
# load json output and parse
|
||||
mds_stat = None
|
||||
try:
|
||||
mds_stat = json.loads(output)
|
||||
except Exception as e:
|
||||
print("MDS ERROR: could not parse '%s' output: %s: %s" % (CEPH_COMMAND,output,e))
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
return check_target_mds(mds_stat, args.filesystem, args.name)
|
||||
|
||||
def check_target_mds(mds_stat, fs_name, name):
|
||||
# find mds from standby list
|
||||
standby_mdss = _get_standby_mds(mds_stat)
|
||||
for mds in standby_mdss:
|
||||
if mds.get_name() == name:
|
||||
print("MDS OK: %s" % (mds))
|
||||
return STATUS_OK
|
||||
|
||||
# find mds from active list
|
||||
active_mdss = _get_active_mds(mds_stat, fs_name)
|
||||
|
||||
if active_mdss:
|
||||
for mds in active_mdss:
|
||||
if mds.get_name() != name:
|
||||
continue
|
||||
# target mds in active list
|
||||
print("MDS %s: %s" % ("WARN" if mds.is_laggy() else "OK", mds))
|
||||
return STATUS_WARNING if mds.is_laggy() else STATUS_OK
|
||||
|
||||
# mds not found
|
||||
print("MDS ERROR: MDS '%s' is not found (offline?)" % (name))
|
||||
return STATUS_ERROR
|
||||
else:
|
||||
# fs not found in map, perhaps user input error
|
||||
print("MDS ERROR: FS '%s' is not found in fsmap" % (fs_name))
|
||||
return STATUS_ERROR
|
||||
|
||||
def _get_standby_mds(mds_stat):
|
||||
mds_array = []
|
||||
for mds in mds_stat['fsmap']['standbys']:
|
||||
name = mds['name']
|
||||
state = mds['state']
|
||||
laggy_since = mds['laggy_since'] if 'laggy_since' in mds else None
|
||||
mds_array.append(MDS(name, state))
|
||||
|
||||
return mds_array
|
||||
|
||||
def _get_active_mds(mds_stat, fs_name):
|
||||
mds_fs = mds_stat['fsmap']['filesystems']
|
||||
|
||||
# find filesystem in stat
|
||||
for i in range(len(mds_fs)):
|
||||
mdsmap = mds_fs[i]['mdsmap']
|
||||
if mdsmap['fs_name'] != fs_name:
|
||||
continue
|
||||
# put mds to array
|
||||
mds_array = []
|
||||
infos = mds_stat['fsmap']['filesystems'][i]['mdsmap']['info']
|
||||
for gid in infos:
|
||||
name = infos[gid]['name']
|
||||
state = infos[gid]['state']
|
||||
laggy_since = infos[gid]['laggy_since'] if 'laggy_since' in infos[gid] else None
|
||||
mds_array.append(MDS(name, state, laggy_since))
|
||||
|
||||
return mds_array
|
||||
|
||||
# no fs found
|
||||
return None
|
||||
|
||||
class MDS(object):
|
||||
def __init__(self, name, state, laggy_since=None):
|
||||
self.name = name
|
||||
self.state = state
|
||||
self.laggy_since = laggy_since
|
||||
|
||||
def get_name(self):
|
||||
return self.name
|
||||
|
||||
def get_state(self):
|
||||
return self.state
|
||||
|
||||
def is_laggy(self):
|
||||
return self.laggy_since is not None
|
||||
|
||||
def __str__(self):
|
||||
msg = "MDS '%s' is %s" % (self.name, self.state)
|
||||
if self.laggy_since is not None:
|
||||
msg += " (laggy or crashed)"
|
||||
return msg
|
||||
|
||||
# main
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
188
nagios-nrpe/files/plugins/check_ceph_mgr
Executable file
188
nagios-nrpe/files/plugins/check_ceph_mgr
Executable file
|
@ -0,0 +1,188 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2018 SWITCH http://www.switch.ch
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import json
|
||||
|
||||
__version__ = '1.0.0'
|
||||
|
||||
# default ceph values
|
||||
CEPH_EXEC = '/usr/bin/ceph'
|
||||
CEPH_COMMAND = 'mgr dump -f json'
|
||||
|
||||
CEPH_MGR_DUMP_EXAMPLE = '''
|
||||
$ ceph --version
|
||||
ceph version 12.2.7 (3ec878d1e53e1aeb47a9f619c49d9e7c0aa384d5) luminous (stable)
|
||||
$ ceph mgr dump -f json|jq .
|
||||
{
|
||||
"epoch": 165,
|
||||
"active_gid": 248001409,
|
||||
"active_name": "zhdk0013",
|
||||
"active_addr": "10.10.10.9:6800/810408",
|
||||
"available": true,
|
||||
"standbys": [
|
||||
{
|
||||
"gid": 247991934,
|
||||
"name": "zhdk0009",
|
||||
"available_modules": [
|
||||
"balancer",
|
||||
"dashboard",
|
||||
"influx",
|
||||
"localpool",
|
||||
"prometheus",
|
||||
"restful",
|
||||
"selftest",
|
||||
"status",
|
||||
"zabbix"
|
||||
]
|
||||
},
|
||||
{
|
||||
"gid": 248011196,
|
||||
"name": "zhdk0025",
|
||||
"available_modules": [
|
||||
"balancer",
|
||||
"dashboard",
|
||||
"influx",
|
||||
"localpool",
|
||||
"prometheus",
|
||||
"restful",
|
||||
"selftest",
|
||||
"status",
|
||||
"zabbix"
|
||||
]
|
||||
}
|
||||
],
|
||||
"modules": [
|
||||
"balancer",
|
||||
"restful",
|
||||
"status"
|
||||
],
|
||||
"available_modules": [
|
||||
"balancer",
|
||||
"dashboard",
|
||||
"influx",
|
||||
"localpool",
|
||||
"prometheus",
|
||||
"restful",
|
||||
"selftest",
|
||||
"status",
|
||||
"zabbix"
|
||||
],
|
||||
"services": {}
|
||||
}
|
||||
'''
|
||||
|
||||
# nagios exit code
|
||||
STATUS_OK = 0
|
||||
STATUS_WARNING = 1
|
||||
STATUS_ERROR = 2
|
||||
STATUS_UNKNOWN = 3
|
||||
|
||||
|
||||
def main():
|
||||
# parse args
|
||||
parser = argparse.ArgumentParser(description="'ceph mgr dump' nagios plugin.")
|
||||
parser.add_argument('-e', '--exe', help='ceph executable [%s]' % CEPH_EXEC)
|
||||
parser.add_argument('-c', '--conf', help='alternative ceph conf file')
|
||||
parser.add_argument('-m', '--monaddress', help='ceph monitor to use for queries (address[:port])')
|
||||
parser.add_argument('-i', '--id', help='ceph client id')
|
||||
parser.add_argument('-n', '--name', help='ceph client name')
|
||||
parser.add_argument('-k', '--keyring', help='ceph client keyring file')
|
||||
parser.add_argument('-V', '--version', help='show version and exit', action='store_true')
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.version:
|
||||
print("version {}".format(__version__))
|
||||
return STATUS_OK
|
||||
|
||||
# validate args
|
||||
ceph_exec = args.exe if args.exe else CEPH_EXEC
|
||||
if not os.path.exists(ceph_exec):
|
||||
print("MGR ERROR: ceph executable '{}' doesn't exist".format(ceph_exec))
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.conf and not os.path.exists(args.conf):
|
||||
print("MGR ERROR: ceph conf file '{}' doesn't exist".format(args.conf))
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.keyring and not os.path.exists(args.keyring):
|
||||
print("MGR ERROR: keyring file '{}' doesn't exist".format(args.keyring))
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
# build command
|
||||
ceph_cmd = [ceph_exec]
|
||||
if args.monaddress:
|
||||
ceph_cmd.append('-m')
|
||||
ceph_cmd.append(args.monaddress)
|
||||
if args.conf:
|
||||
ceph_cmd.append('-c')
|
||||
ceph_cmd.append(args.conf)
|
||||
if args.id:
|
||||
ceph_cmd.append('--id')
|
||||
ceph_cmd.append(args.id)
|
||||
if args.name:
|
||||
ceph_cmd.append('--name')
|
||||
ceph_cmd.append(args.name)
|
||||
if args.keyring:
|
||||
ceph_cmd.append('--keyring')
|
||||
ceph_cmd.append(args.keyring)
|
||||
ceph_cmd.extend(CEPH_COMMAND.split(' '))
|
||||
|
||||
# exec command
|
||||
p = subprocess.Popen(ceph_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
output, err = p.communicate()
|
||||
|
||||
if p.returncode != 0 or not output:
|
||||
print("MGR ERROR: {}".format(err))
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
# load json output and parse
|
||||
mgr_dump = None
|
||||
try:
|
||||
mgr_dump = json.loads(output)
|
||||
except Exception as e:
|
||||
print("MGR ERROR: could not parse '{}' output: {}: {}".format(ceph_cmd, output, e))
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
# check active
|
||||
if 'active_name' not in mgr_dump:
|
||||
print("MGR CRITICAL: not active mgr found")
|
||||
print("JSON: {}".format(json.dumps(mgr_dump)))
|
||||
return STATUS_ERROR
|
||||
|
||||
active_mgr_name = mgr_dump['active_name']
|
||||
# check standby
|
||||
standby_mgr_names = []
|
||||
for standby_mgr in mgr_dump['standbys']:
|
||||
standby_mgr_names.append(standby_mgr['name'])
|
||||
|
||||
if len(standby_mgr_names) <= 0:
|
||||
print("MGR WARN: active: {} but no standbys".format(active_mgr_name))
|
||||
return STATUS_WARNING
|
||||
else:
|
||||
print("MGR OK: active: {}, standbys: {}".format(active_mgr_name,
|
||||
", ".join(standby_mgr_names)))
|
||||
return STATUS_OK
|
||||
|
||||
# main
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
163
nagios-nrpe/files/plugins/check_ceph_mon
Executable file
163
nagios-nrpe/files/plugins/check_ceph_mon
Executable file
|
@ -0,0 +1,163 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2013 Catalyst IT http://www.catalyst.net.nz
|
||||
# Copyright (c) 2015 SWITCH http://www.switch.ch
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import socket
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import json
|
||||
|
||||
__version__ = '1.5.0'
|
||||
|
||||
# default ceph values
|
||||
CEPH_EXEC = '/usr/bin/ceph'
|
||||
CEPH_COMMAND = 'quorum_status'
|
||||
|
||||
# nagios exit code
|
||||
STATUS_OK = 0
|
||||
STATUS_WARNING = 1
|
||||
STATUS_ERROR = 2
|
||||
STATUS_UNKNOWN = 3
|
||||
|
||||
##
|
||||
# ceph quorum_status output example
|
||||
##
|
||||
ceph_quorum_status_output_example = '''{
|
||||
"quorum_leader_name" : "s0001",
|
||||
"monmap" : {
|
||||
"mons" : [
|
||||
{
|
||||
"name" : "s0001",
|
||||
"addr" : "[2001:620:5ca1:8000::1001]:6789/0",
|
||||
"rank" : 0
|
||||
},
|
||||
{
|
||||
"name" : "s0003",
|
||||
"addr" : "[2001:620:5ca1:8000::1003]:6789/0",
|
||||
"rank" : 1
|
||||
}
|
||||
],
|
||||
"created" : "2014-12-15 08:28:35.153650",
|
||||
"epoch" : 2,
|
||||
"modified" : "2014-12-15 08:28:40.371878",
|
||||
"fsid" : "22348d2b-b69d-46cc-9a79-ca93cd6bae84"
|
||||
},
|
||||
"quorum_names" : [
|
||||
"s0001",
|
||||
"s0003"
|
||||
],
|
||||
"quorum" : [
|
||||
0,
|
||||
1
|
||||
],
|
||||
"election_epoch" : 24
|
||||
}'''
|
||||
|
||||
def main():
|
||||
|
||||
# parse args
|
||||
parser = argparse.ArgumentParser(description="'ceph quorum_status' nagios plugin.")
|
||||
parser.add_argument('-e','--exe', help='ceph executable [%s]' % CEPH_EXEC)
|
||||
parser.add_argument('-c','--conf', help='alternative ceph conf file')
|
||||
parser.add_argument('-m','--monaddress', help='ceph monitor to use for queries (address[:port])')
|
||||
parser.add_argument('-i','--id', help='ceph client id')
|
||||
parser.add_argument('-k','--keyring', help='ceph client keyring file')
|
||||
parser.add_argument('-V','--version', help='show version and exit', action='store_true')
|
||||
parser.add_argument('-I','--monid', help='mon ID to be checked for availability')
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.version:
|
||||
print('version %s' % __version__)
|
||||
return STATUS_OK
|
||||
|
||||
# validate args
|
||||
ceph_exec = args.exe if args.exe else CEPH_EXEC
|
||||
if not os.path.exists(ceph_exec):
|
||||
print("MON ERROR: ceph executable '%s' doesn't exist" % ceph_exec)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.conf and not os.path.exists(args.conf):
|
||||
print("MON ERROR: ceph conf file '%s' doesn't exist" % args.conf)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.keyring and not os.path.exists(args.keyring):
|
||||
print("MON ERROR: keyring file '%s' doesn't exist" % args.keyring)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if not args.monid:
|
||||
print("MON ERROR: no MON ID given, use -I/--monid parameter")
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
# build command
|
||||
ceph_cmd = [ceph_exec]
|
||||
if args.monaddress:
|
||||
ceph_cmd.append('-m')
|
||||
ceph_cmd.append(args.monaddress)
|
||||
if args.conf:
|
||||
ceph_cmd.append('-c')
|
||||
ceph_cmd.append(args.conf)
|
||||
if args.id:
|
||||
ceph_cmd.append('--id')
|
||||
ceph_cmd.append(args.id)
|
||||
if args.keyring:
|
||||
ceph_cmd.append('--keyring')
|
||||
ceph_cmd.append(args.keyring)
|
||||
ceph_cmd.append(CEPH_COMMAND)
|
||||
|
||||
# exec command
|
||||
p = subprocess.Popen(ceph_cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
||||
output, err = p.communicate()
|
||||
|
||||
if p.returncode != 0 or not output:
|
||||
print("MON ERROR: %s" % err)
|
||||
return STATUS_ERROR
|
||||
|
||||
# load json output and parse
|
||||
quorum_status = False
|
||||
try:
|
||||
quorum_status = json.loads(output)
|
||||
except Exception as e:
|
||||
print("MON ERROR: could not parse '%s' output: %s: %s" % (CEPH_COMMAND,output,e))
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
#print "XXX: quorum_status['quorum_names']:", quorum_status['quorum_names']
|
||||
|
||||
# do our checks
|
||||
is_monitor = False
|
||||
for mon in quorum_status['monmap']['mons']:
|
||||
if mon['name'] == args.monid:
|
||||
is_monitor = True
|
||||
if not is_monitor:
|
||||
print("MON WARN: mon '%s' is not in monmap: %s" % (args.monid,quorum_status['monmap']['mons']))
|
||||
return STATUS_WARNING
|
||||
|
||||
in_quorum = args.monid in quorum_status['quorum_names']
|
||||
if in_quorum:
|
||||
print("MON OK")
|
||||
return STATUS_OK
|
||||
else:
|
||||
print("MON WARN: no MON '%s' found in quorum" % args.monid)
|
||||
return STATUS_WARNING
|
||||
|
||||
# main
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
154
nagios-nrpe/files/plugins/check_ceph_osd
Executable file
154
nagios-nrpe/files/plugins/check_ceph_osd
Executable file
|
@ -0,0 +1,154 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2013 Catalyst IT http://www.catalyst.net.nz
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# 1.5.2 (2019-06-16) Martin Seener: fixed regex to work with Ceph Nautilus (14.2.x)
|
||||
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import socket
|
||||
|
||||
__version__ = '1.5.2'
|
||||
|
||||
# default ceph values
|
||||
CEPH_COMMAND = '/usr/bin/ceph'
|
||||
|
||||
# nagios exit code
|
||||
STATUS_OK = 0
|
||||
STATUS_WARNING = 1
|
||||
STATUS_ERROR = 2
|
||||
STATUS_UNKNOWN = 3
|
||||
|
||||
def main():
|
||||
|
||||
# parse args
|
||||
parser = argparse.ArgumentParser(description="'ceph osd' nagios plugin.")
|
||||
parser.add_argument('-e','--exe', help='ceph executable [%s]' % CEPH_COMMAND)
|
||||
parser.add_argument('-c','--conf', help='alternative ceph conf file')
|
||||
parser.add_argument('-m','--monaddress', help='ceph monitor address[:port]')
|
||||
parser.add_argument('-i','--id', help='ceph client id')
|
||||
parser.add_argument('-k','--keyring', help='ceph client keyring file')
|
||||
parser.add_argument('-V','--version', help='show version and exit', action='store_true')
|
||||
parser.add_argument('-H','--host', help='osd host', required=True)
|
||||
parser.add_argument('-I','--osdid', help='osd id', required=False)
|
||||
parser.add_argument('-C','--crit', help='Number of failed OSDs to trigger critical (default=2)',type=int,default=2, required=False)
|
||||
parser.add_argument('-o','--out', help='check osds that are set OUT', default=False, action='store_true', required=False)
|
||||
args = parser.parse_args()
|
||||
|
||||
# validate args
|
||||
ceph_exec = args.exe if args.exe else CEPH_COMMAND
|
||||
if not os.path.exists(ceph_exec):
|
||||
print("OSD ERROR: ceph executable '%s' doesn't exist" % ceph_exec)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.version:
|
||||
print('version %s' % __version__)
|
||||
return STATUS_OK
|
||||
|
||||
if args.conf and not os.path.exists(args.conf):
|
||||
print("OSD ERROR: ceph conf file '%s' doesn't exist" % args.conf)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.keyring and not os.path.exists(args.keyring):
|
||||
print("OSD ERROR: keyring file '%s' doesn't exist" % args.keyring)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if not args.osdid:
|
||||
args.osdid = '[^ ]*'
|
||||
|
||||
if not args.host:
|
||||
print("OSD ERROR: no OSD hostname given")
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
try:
|
||||
addrinfo = socket.getaddrinfo(args.host, None, 0, socket.SOCK_STREAM)
|
||||
args.host = addrinfo[0][-1][0]
|
||||
if addrinfo[0][0] == socket.AF_INET6:
|
||||
args.host = "[%s]" % args.host
|
||||
except:
|
||||
print('OSD ERROR: could not resolve %s' % args.host)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
|
||||
# build command
|
||||
ceph_cmd = [ceph_exec]
|
||||
if args.monaddress:
|
||||
ceph_cmd.append('-m')
|
||||
ceph_cmd.append(args.monaddress)
|
||||
if args.conf:
|
||||
ceph_cmd.append('-c')
|
||||
ceph_cmd.append(args.conf)
|
||||
if args.id:
|
||||
ceph_cmd.append('--id')
|
||||
ceph_cmd.append(args.id)
|
||||
if args.keyring:
|
||||
ceph_cmd.append('--keyring')
|
||||
ceph_cmd.append(args.keyring)
|
||||
ceph_cmd.append('osd')
|
||||
ceph_cmd.append('dump')
|
||||
|
||||
# exec command
|
||||
p = subprocess.Popen(ceph_cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
||||
output, err = p.communicate()
|
||||
output = output.decode('utf8')
|
||||
|
||||
if err or not output:
|
||||
print("OSD ERROR: %s" % err)
|
||||
return STATUS_ERROR
|
||||
|
||||
# escape IPv4 host address
|
||||
osd_host = args.host.replace('.', '\.')
|
||||
# escape IPv6 host address
|
||||
osd_host = osd_host.replace('[', '\[')
|
||||
osd_host = osd_host.replace(']', '\]')
|
||||
up = re.findall(r"^(osd\.%s) up.*%s:" % (args.osdid, osd_host), output, re.MULTILINE)
|
||||
if args.out:
|
||||
down = re.findall(r"^(osd\.%s) down.*%s:" % (args.osdid, osd_host), output, re.MULTILINE)
|
||||
down_in = re.findall(r"^(osd\.%s) down[ ]+in.*%s:" % (args.osdid, osd_host), output, re.MULTILINE)
|
||||
down_out = re.findall(r"^(osd\.%s) down[ ]+out.*%s:" % (args.osdid, osd_host), output, re.MULTILINE)
|
||||
else:
|
||||
down = re.findall(r"^(osd\.%s) down[ ]+in.*%s:" % (args.osdid, osd_host), output, re.MULTILINE)
|
||||
down_in = down
|
||||
down_out = re.findall(r"^(osd\.%s) down[ ]+out.*%s:" % (args.osdid, osd_host), output, re.MULTILINE)
|
||||
|
||||
if down:
|
||||
print("OSD %s: Down OSD%s on %s: %s" % ('CRITICAL' if len(down)>=args.crit else 'WARNING' ,'s' if len(down)>1 else '', args.host, " ".join(down)))
|
||||
print("Up OSDs: " + " ".join(up))
|
||||
print("Down+In OSDs: " + " ".join(down_in))
|
||||
print("Down+Out OSDs: " + " ".join(down_out))
|
||||
print("| 'osd_up'=%d 'osd_down_in'=%d;;%d 'osd_down_out'=%d;;%d" % (len(up), len(down_in), args.crit, len(down_out), args.crit))
|
||||
if len(down)>=args.crit:
|
||||
return STATUS_ERROR
|
||||
else:
|
||||
return STATUS_WARNING
|
||||
|
||||
if up:
|
||||
print("OSD OK")
|
||||
print("Up OSDs: " + " ".join(up))
|
||||
print("Down+In OSDs: " + " ".join(down_in))
|
||||
print("Down+Out OSDs: " + " ".join(down_out))
|
||||
print("| 'osd_up'=%d 'osd_down_in'=%d;;%d 'osd_down_out'=%d;;%d" % (len(up), len(down_in), args.crit, len(down_out), args.crit))
|
||||
return STATUS_OK
|
||||
|
||||
print("OSD WARN: no OSD.%s found on host %s" % (args.osdid, args.host))
|
||||
return STATUS_WARNING
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
152
nagios-nrpe/files/plugins/check_ceph_osd_db
Executable file
152
nagios-nrpe/files/plugins/check_ceph_osd_db
Executable file
|
@ -0,0 +1,152 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2020 Binero AB https://binero.com
|
||||
# Copyright (c) 2013 Catalyst IT http://www.catalyst.net.nz
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import socket
|
||||
import json
|
||||
|
||||
|
||||
CEPH_COMMAND = '/usr/bin/ceph'
|
||||
|
||||
STATUS_OK = 0
|
||||
STATUS_CRITICAL = 2
|
||||
STATUS_UNKNOWN = 3
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="'ceph osd' nagios plugin.")
|
||||
|
||||
parser.add_argument('-e','--exe', help='ceph executable [%s]' % CEPH_COMMAND)
|
||||
parser.add_argument('-c','--conf', help='alternative ceph conf file')
|
||||
parser.add_argument('-m','--monaddress', help='ceph monitor address[:port]')
|
||||
parser.add_argument('-i','--id', help='ceph client id')
|
||||
parser.add_argument('-k','--keyring', help='ceph client keyring file')
|
||||
parser.add_argument('-H','--host', help='osd host', required=True)
|
||||
parser.add_argument('-C','--critical', help='critical threshold', default=60)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
ceph_exec = args.exe if args.exe else CEPH_COMMAND
|
||||
if not os.path.exists(ceph_exec):
|
||||
print("UNKNOWN: ceph executable '%s' doesn't exist" % ceph_exec)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.conf and not os.path.exists(args.conf):
|
||||
print("UNKNOWN: ceph conf file '%s' doesn't exist" % args.conf)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.keyring and not os.path.exists(args.keyring):
|
||||
print("UNKNOWN: keyring file '%s' doesn't exist" % args.keyring)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if not args.host:
|
||||
print("UNKNOWN: no OSD hostname given")
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
try:
|
||||
addrinfo = socket.getaddrinfo(args.host, None, 0, socket.SOCK_STREAM)
|
||||
args.host = addrinfo[0][-1][0]
|
||||
if addrinfo[0][0] == socket.AF_INET6:
|
||||
args.host = "[%s]" % args.host
|
||||
except Exception:
|
||||
print('UNKNOWN: could not resolve %s' % args.host)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
ceph_cmd = [ceph_exec]
|
||||
if args.monaddress:
|
||||
ceph_cmd.append('-m')
|
||||
ceph_cmd.append(args.monaddress)
|
||||
if args.conf:
|
||||
ceph_cmd.append('-c')
|
||||
ceph_cmd.append(args.conf)
|
||||
if args.id:
|
||||
ceph_cmd.append('--id')
|
||||
ceph_cmd.append(args.id)
|
||||
if args.keyring:
|
||||
ceph_cmd.append('--keyring')
|
||||
ceph_cmd.append(args.keyring)
|
||||
|
||||
ceph_cmd.append('osd')
|
||||
ceph_cmd.append('dump')
|
||||
|
||||
p = subprocess.Popen(ceph_cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
||||
output, err = p.communicate()
|
||||
|
||||
if err or not output:
|
||||
print("CRITICAL: %s" % err)
|
||||
return STATUS_CRITICAL
|
||||
|
||||
# escape IPv4 host address
|
||||
osd_host = args.host.replace('.', '\.')
|
||||
# escape IPv6 host address
|
||||
osd_host = osd_host.replace('[', '\[')
|
||||
osd_host = osd_host.replace(']', '\]')
|
||||
|
||||
osds_up = re.findall(r"^(osd\.[^ ]*) up.*%s:" % (osd_host), output, re.MULTILINE)
|
||||
|
||||
final_status = STATUS_OK
|
||||
lines = []
|
||||
|
||||
for osd in osds_up:
|
||||
daemon_ceph_cmd = [ceph_exec, '--format', 'json']
|
||||
daemon_ceph_cmd.append('daemon')
|
||||
daemon_ceph_cmd.append(osd)
|
||||
daemon_ceph_cmd.append('perf')
|
||||
daemon_ceph_cmd.append('dump')
|
||||
|
||||
p = subprocess.Popen(daemon_ceph_cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
||||
output, err = p.communicate()
|
||||
|
||||
if err or not output:
|
||||
print("CRITICAL: %s" % err)
|
||||
return STATUS_CRITICAL
|
||||
|
||||
try:
|
||||
data = json.loads(output)
|
||||
except Exception:
|
||||
print("CRITICAL: failed to load json")
|
||||
return STATUS_CRITICAL
|
||||
|
||||
bluefs = data.get('bluefs', None)
|
||||
|
||||
if not bluefs:
|
||||
continue
|
||||
|
||||
db_total_bytes = bluefs.get('db_total_bytes')
|
||||
db_used_bytes = bluefs.get('db_used_bytes')
|
||||
perc = (float(db_used_bytes) / float(db_total_bytes) * 100)
|
||||
|
||||
if perc >= args.critical and final_status == STATUS_OK:
|
||||
final_status = STATUS_CRITICAL
|
||||
|
||||
lines.append("%s=%.2f%%" % (osd, perc))
|
||||
|
||||
if final_status == STATUS_OK:
|
||||
print("OK: %s" % (' '.join(lines)))
|
||||
else:
|
||||
print("CRITICAL: %s" % (' '.join(lines)))
|
||||
|
||||
return final_status
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
153
nagios-nrpe/files/plugins/check_ceph_osd_df
Executable file
153
nagios-nrpe/files/plugins/check_ceph_osd_df
Executable file
|
@ -0,0 +1,153 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# check_ceph_osd_df - Check OSD DF output
|
||||
# Copyright (c) 2020 noris network AG https://www.noris.de
|
||||
#
|
||||
# This plugin will not output perfdata as there is likely a lot of output
|
||||
# which should be gathered using other tools.
|
||||
#
|
||||
# Parts based on code from check_ceph_df which is
|
||||
# Copyright (c) 2013 SWITCH http://www.switch.ch
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import json
|
||||
from operator import itemgetter
|
||||
|
||||
# Semver
|
||||
__version__ = '1.0.0'
|
||||
|
||||
# default ceph values
|
||||
CEPH_COMMAND = '/usr/bin/ceph'
|
||||
|
||||
# nagios exit code
|
||||
STATUS_OK = 0
|
||||
STATUS_WARNING = 1
|
||||
STATUS_ERROR = 2
|
||||
STATUS_UNKNOWN = 3
|
||||
|
||||
def main():
|
||||
|
||||
# parse args
|
||||
parser = argparse.ArgumentParser(description="'ceph osd df' nagios plugin.")
|
||||
parser.add_argument('-e','--exe', help='ceph executable [%s]' % CEPH_COMMAND)
|
||||
parser.add_argument('-c','--conf', help='alternative ceph conf file')
|
||||
parser.add_argument('-m','--monaddress', help='ceph monitor address[:port]')
|
||||
parser.add_argument('-i','--id', help='ceph client id')
|
||||
parser.add_argument('-n','--name', help='ceph client name')
|
||||
parser.add_argument('-k','--keyring', help='ceph client keyring file')
|
||||
parser.add_argument('-W','--warn', help="warn above this percent USED", type=float)
|
||||
parser.add_argument('-C','--critical', help="critical alert above this percent USED", type=float)
|
||||
parser.add_argument('-V','--version', help='show version and exit', action='store_true')
|
||||
args = parser.parse_args()
|
||||
|
||||
# validate args
|
||||
ceph_exec = args.exe if args.exe else CEPH_COMMAND
|
||||
if not os.path.exists(ceph_exec):
|
||||
print("ERROR: ceph executable '%s' doesn't exist" % ceph_exec)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.version:
|
||||
print('version %s' % __version__)
|
||||
return STATUS_OK
|
||||
|
||||
if args.conf and not os.path.exists(args.conf):
|
||||
print("ERROR: ceph conf file '%s' doesn't exist" % args.conf)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.keyring and not os.path.exists(args.keyring):
|
||||
print("ERROR: keyring file '%s' doesn't exist" % args.keyring)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if not args.warn or not args.critical or args.warn > args.critical:
|
||||
print("ERROR: warn and critical level must be set and critical must be greater than warn")
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
# build command
|
||||
ceph_osd_df = [ceph_exec]
|
||||
if args.monaddress:
|
||||
ceph_osd_df.append('-m')
|
||||
ceph_osd_df.append(args.monaddress)
|
||||
if args.conf:
|
||||
ceph_osd_df.append('-c')
|
||||
ceph_osd_df.append(args.conf)
|
||||
if args.id:
|
||||
ceph_osd_df.append('--id')
|
||||
ceph_osd_df.append(args.id)
|
||||
if args.name:
|
||||
ceph_osd_df.append('--name')
|
||||
ceph_osd_df.append(args.name)
|
||||
if args.keyring:
|
||||
ceph_osd_df.append('--keyring')
|
||||
ceph_osd_df.append(args.keyring)
|
||||
ceph_osd_df.append('osd')
|
||||
ceph_osd_df.append('df')
|
||||
ceph_osd_df.append('--format=json')
|
||||
|
||||
# exec command
|
||||
p = subprocess.Popen(ceph_osd_df,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
||||
output, err = p.communicate()
|
||||
|
||||
# parse output
|
||||
# print "DEBUG: output:", output
|
||||
# print "DEBUG: err:", err
|
||||
if output:
|
||||
# parse output
|
||||
try:
|
||||
result = json.loads(output)
|
||||
check_return_value = STATUS_OK
|
||||
nodes_sorted = sorted(result["nodes"], key=itemgetter('utilization','id'))
|
||||
|
||||
warn_crit_osds = []
|
||||
|
||||
for node in reversed(nodes_sorted):
|
||||
if node["utilization"] >= args.warn and check_return_value is not STATUS_ERROR:
|
||||
check_return_value = STATUS_WARNING
|
||||
warn_crit_osds.append("{}={:04.2f}".format(node["name"], node["utilization"]))
|
||||
|
||||
if node["utilization"] >= args.critical:
|
||||
check_return_value = STATUS_ERROR
|
||||
warn_crit_osds.append("{}={:04.2f}".format(node["name"], node["utilization"]))
|
||||
|
||||
if check_return_value == STATUS_OK:
|
||||
print("OK: All OSDs within limits")
|
||||
return STATUS_OK
|
||||
elif check_return_value == STATUS_WARNING:
|
||||
print("WARNING: OSD usage above warn threshold: {:.4054}".format(", ".join(warn_crit_osds)))
|
||||
return STATUS_WARNING
|
||||
elif check_return_value == STATUS_ERROR:
|
||||
print("CRITICAL: OSD usage above critical or warn threshold: {:.4041}".format(", ".join(warn_crit_osds)))
|
||||
return STATUS_ERROR
|
||||
except:
|
||||
print("ERROR: {}".format(sys.exc_info()[0]))
|
||||
return STATUS_UNKNOWN
|
||||
elif err:
|
||||
# read only first line of error
|
||||
one_line = err.split('\n')[0]
|
||||
if '-1 ' in one_line:
|
||||
idx = one_line.rfind('-1 ')
|
||||
print('ERROR: %s: %s' % (ceph_exec, one_line[idx+len('-1 '):]))
|
||||
else:
|
||||
print(one_line)
|
||||
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
118
nagios-nrpe/files/plugins/check_ceph_rgw
Executable file
118
nagios-nrpe/files/plugins/check_ceph_rgw
Executable file
|
@ -0,0 +1,118 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Catalyst IT http://www.catalyst.net.nz
|
||||
# Copyright (c) 2015 SWITCH http://www.switch.ch
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import json
|
||||
|
||||
__version__ = '1.5.1'
|
||||
|
||||
# default ceph values
|
||||
RGW_COMMAND = '/usr/bin/radosgw-admin'
|
||||
|
||||
# nagios exit code
|
||||
STATUS_OK = 0
|
||||
STATUS_WARNING = 1
|
||||
STATUS_ERROR = 2
|
||||
STATUS_UNKNOWN = 3
|
||||
|
||||
def main():
|
||||
|
||||
# parse args
|
||||
parser = argparse.ArgumentParser(description="'radosgw-admin bucket stats' nagios plugin.")
|
||||
parser.add_argument('-d','--detail', help='output perf data for all buckets', action='store_true')
|
||||
parser.add_argument('-B','--byte', help='output perf data in Byte instead of KB', action='store_true')
|
||||
parser.add_argument('-e','--exe', help='radosgw-admin executable [%s]' % RGW_COMMAND)
|
||||
parser.add_argument('-c','--conf', help='alternative ceph conf file')
|
||||
parser.add_argument('-i','--id', help='ceph client id')
|
||||
parser.add_argument('-n','--name', help='ceph client name (type.id)')
|
||||
parser.add_argument('-V','--version', help='show version and exit', action='store_true')
|
||||
args = parser.parse_args()
|
||||
|
||||
# validate args
|
||||
rgw_exec = args.exe if args.exe else RGW_COMMAND
|
||||
if not os.path.exists(rgw_exec):
|
||||
print("RGW ERROR: radosgw-admin executable '%s' doesn't exist" % rgw_exec)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
if args.version:
|
||||
print('version %s' % __version__)
|
||||
return STATUS_OK
|
||||
|
||||
if args.conf and not os.path.exists(args.conf):
|
||||
print("RGW ERROR: ceph conf file '%s' doesn't exist" % args.conf)
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
# build command
|
||||
rgw_cmd = [rgw_exec]
|
||||
if args.conf:
|
||||
rgw_cmd.append('-c')
|
||||
rgw_cmd.append(args.conf)
|
||||
if args.id:
|
||||
rgw_cmd.append('--id')
|
||||
rgw_cmd.append(args.id)
|
||||
if args.name:
|
||||
rgw_cmd.append('-n')
|
||||
rgw_cmd.append(args.name)
|
||||
rgw_cmd.append('bucket')
|
||||
rgw_cmd.append('stats')
|
||||
|
||||
# exec command
|
||||
p = subprocess.Popen(rgw_cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
||||
output, err = p.communicate()
|
||||
|
||||
if p.returncode != 0 or not output:
|
||||
print("RGW ERROR: %s :: %s" % (output, err))
|
||||
return STATUS_ERROR
|
||||
|
||||
bucket_stats = json.loads(output)
|
||||
#print bucket_stats
|
||||
|
||||
buckets = []
|
||||
for i in bucket_stats:
|
||||
if type(i) is dict:
|
||||
bucket_name = i['bucket']
|
||||
usage_dict = i['usage']
|
||||
if usage_dict and 'rgw.main' in usage_dict:
|
||||
bucket_usage_kb = usage_dict['rgw.main']['size_kb_actual']
|
||||
else:
|
||||
bucket_usage_kb = 0
|
||||
buckets.append((bucket_name, bucket_usage_kb))
|
||||
buckets_total_kb = sum([b[1] for b in buckets])
|
||||
|
||||
if args.byte:
|
||||
status = "RGW OK: {} buckets, {} KB total | /={}B ".format(len(buckets),buckets_total_kb,buckets_total_kb*1024)
|
||||
else:
|
||||
status = "RGW OK: {} buckets, {} KB total | /={}KB ".format(len(buckets),buckets_total_kb,buckets_total_kb)
|
||||
#print buckets
|
||||
if buckets and args.detail:
|
||||
if args.byte:
|
||||
status = status + " ".join(["{}={}B".format(b[0],b[1]*1024) for b in buckets])
|
||||
else:
|
||||
status = status + " ".join(["{}={}KB".format(b[0],b[1]) for b in buckets])
|
||||
|
||||
print(status)
|
||||
return STATUS_OK
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
116
nagios-nrpe/files/plugins/check_ceph_rgw_api
Executable file
116
nagios-nrpe/files/plugins/check_ceph_rgw_api
Executable file
|
@ -0,0 +1,116 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Catalyst IT http://www.catalyst.net.nz
|
||||
# Copyright (c) 2015 SWITCH http://www.switch.ch
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import print_function
|
||||
import requests
|
||||
import warnings
|
||||
import json
|
||||
import argparse
|
||||
import sys
|
||||
from awsauth import S3Auth
|
||||
|
||||
__version__ = '1.7.2'
|
||||
|
||||
# nagios exit code
|
||||
STATUS_OK = 0
|
||||
STATUS_WARNING = 1
|
||||
STATUS_CRITICAL = 2
|
||||
STATUS_UNKNOWN = 3
|
||||
|
||||
def main():
|
||||
|
||||
# parse args
|
||||
parser = argparse.ArgumentParser(description="'radosgw api bucket stats' nagios plugin.")
|
||||
parser.add_argument('-H', '--host', help="Server URL for the radosgw api (example: http://objects.dreamhost.com/)", required=True)
|
||||
parser.add_argument('-k', '--insecure', help="Allow insecure server connections when using SSL", action="store_false")
|
||||
parser.add_argument('-e', '--admin_entry', help="The entry point for an admin request URL [default is '%(default)s']", default="admin")
|
||||
parser.add_argument('-a', '--access_key', help="S3 access key", required=True)
|
||||
parser.add_argument('-s', '--secret_key', help="S3 secret key", required=True)
|
||||
parser.add_argument('-d', '--detail', help="output perf data for all buckets", action="store_true")
|
||||
parser.add_argument('-b', '--byte', help="output perf data in Byte instead of KB", action="store_true")
|
||||
parser.add_argument('-v', '--version', help='show version and exit', action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.version:
|
||||
print("version {0}".format(__version__))
|
||||
return STATUS_OK
|
||||
|
||||
# helpers for default schema
|
||||
if not args.host.startswith("http"):
|
||||
args.host = "http://{0}".format(args.host)
|
||||
# and for request_uri
|
||||
if not args.host.endswith("/"):
|
||||
args.host = "{0}/".format(args.host)
|
||||
|
||||
url = "{0}{1}/bucket?format=json&stats=True".format(args.host,
|
||||
args.admin_entry)
|
||||
|
||||
try:
|
||||
# Inversion of condition, when '--insecure' is defined we disable
|
||||
# requests warning about certificate hostname mismatch.
|
||||
if not args.insecure:
|
||||
warnings.filterwarnings('ignore', message='Unverified HTTPS request')
|
||||
|
||||
response = requests.get(url, verify=args.insecure,
|
||||
auth=S3Auth(args.access_key, args.secret_key,
|
||||
args.host))
|
||||
|
||||
if response.status_code == requests.codes.ok:
|
||||
bucket_stats = response.json()
|
||||
else:
|
||||
# no usage caps or wrong admin entry
|
||||
print("RGW ERROR [{0}]: {1}".format(response.status_code,
|
||||
response.content.decode('utf-8')))
|
||||
return STATUS_WARNING
|
||||
|
||||
# DNS, connection errors, etc
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("RGW ERROR: {0}".format(e))
|
||||
return STATUS_UNKNOWN
|
||||
|
||||
#print(bucket_stats)
|
||||
buckets = []
|
||||
for i in bucket_stats:
|
||||
if type(i) is dict:
|
||||
bucket_name = i['bucket']
|
||||
usage_dict = i['usage']
|
||||
if usage_dict and 'rgw.main' in usage_dict:
|
||||
bucket_usage_kb = usage_dict['rgw.main']['size_kb_actual']
|
||||
else:
|
||||
bucket_usage_kb = 0
|
||||
buckets.append((bucket_name, bucket_usage_kb))
|
||||
buckets_total_kb = sum([b[1] for b in buckets])
|
||||
|
||||
status = "RGW OK: {0} buckets, {1} KB total | /={2}{3} "
|
||||
|
||||
if args.byte:
|
||||
status = status.format(len(buckets), buckets_total_kb, buckets_total_kb*1024, "B")
|
||||
else:
|
||||
status = status.format(len(buckets), buckets_total_kb, buckets_total_kb, "KB")
|
||||
#print(buckets)
|
||||
if buckets and args.detail:
|
||||
if args.byte:
|
||||
status = status + " ".join(["{}={}B".format(b[0], b[1]*1024) for b in buckets])
|
||||
else:
|
||||
status = status + " ".join(["{}={}KB".format(b[0], b[1]) for b in buckets])
|
||||
|
||||
print(status)
|
||||
return STATUS_OK
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
|
@ -5,6 +5,7 @@
|
|||
# Copyright (C) 2012, Giacomo Montagner <giacomo@entirelyunlike.net>
|
||||
# 2015, Yann Fertat, Romain Dessort, Jeff Palmer,
|
||||
# Christophe Drevet-Droguet <dr4ke@dr4ke.net>
|
||||
# 2022, Jérémy Lecour <jlecour@evolix.fr>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the same terms as Perl 5.10.1.
|
||||
|
@ -15,7 +16,7 @@
|
|||
# warranty of merchantability or fitness for a particular purpose.
|
||||
#
|
||||
|
||||
our $VERSION = "1.2.0";
|
||||
our $VERSION = "1.3.1";
|
||||
|
||||
open(STDERR, ">&STDOUT");
|
||||
|
||||
|
@ -29,6 +30,8 @@ open(STDERR, ">&STDOUT");
|
|||
# 1.1.0 - support for HTTP interface
|
||||
# 1.1.1 - drop perl 5.10 requirement
|
||||
# 1.2.0 - add an option for ignore NOLB
|
||||
# 1.3.0 - add an option for ignore DRAIN
|
||||
# 1.3.1 - support DRAIN/MAINT when set by agent
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
@ -64,6 +67,8 @@ DESCRIPTION
|
|||
Assume servers in MAINT state to be ok.
|
||||
-n, --ignore-nolb
|
||||
Assume servers in NOLB state to be ok.
|
||||
--ignore-drain
|
||||
Assume servers in DRAIN state to be ok.
|
||||
-p, --proxy
|
||||
Check only named proxies, not every one. Use comma to separate proxies
|
||||
in list.
|
||||
|
@ -132,6 +137,7 @@ my $pass = '';
|
|||
my $dump;
|
||||
my $ignore_maint;
|
||||
my $ignore_nolb;
|
||||
my $ignore_drain;
|
||||
my $proxy;
|
||||
my $no_proxy;
|
||||
my $help;
|
||||
|
@ -143,7 +149,8 @@ GetOptions (
|
|||
"d|dump" => \$dump,
|
||||
"h|help" => \$help,
|
||||
"m|ignore-maint" => \$ignore_maint,
|
||||
"n|ignore-nolb" => \$ignore_nolb,
|
||||
"n|ignore-nolb" => \$ignore_nolb,
|
||||
"ignore-drain" => \$ignore_drain,
|
||||
"p|proxy=s" => \$proxy,
|
||||
"P|no-proxy=s" => \$no_proxy,
|
||||
"s|sock|socket=s" => \$sock,
|
||||
|
@ -267,8 +274,9 @@ foreach (@hastats) {
|
|||
# Check of servers
|
||||
} else {
|
||||
if ($data[$status] ne 'UP') {
|
||||
next if ($ignore_maint && $data[$status] eq 'MAINT');
|
||||
next if ($ignore_maint && ($data[$status] eq 'MAINT' || $data[$status] eq 'MAINT (agent)'));
|
||||
next if ($ignore_nolb && $data[$status] eq 'NOLB');
|
||||
next if ($ignore_drain && ($data[$status] eq 'DRAIN' || $data[$status] eq 'DRAIN (agent)'));
|
||||
next if $data[$status] eq 'no check'; # Ignore server if no check is configured to be run
|
||||
next if $data[$svname] eq 'sock-1';
|
||||
$exitcode = 2;
|
||||
|
|
|
@ -51,7 +51,7 @@ command[check_ssl]=/usr/lib/nagios/plugins/check_http -f follow -I 127.0.0.1 -S
|
|||
command[check_ssl_local]={{ nagios_plugins_directory }}/check_ssl_local
|
||||
command[check_elasticsearch]=/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -u /_cat/health?h=st -p 9200 -r 'red' --invert-regex
|
||||
command[check_memcached]=/usr/lib/nagios/plugins/check_tcp -H 127.0.0.1 -p 11211
|
||||
command[check_opendkim]=/usr/lib/nagios/plugins/check_tcp -H 127.0.0.1 -p 54321
|
||||
command[check_opendkim]=/usr/lib/nagios/plugins/check_tcp -H 127.0.0.1 -p 8891
|
||||
command[check_bkctld_setup]=sudo /usr/sbin/bkctld check-setup
|
||||
command[check_bkctld_jails]=sudo /usr/sbin/bkctld check-jails
|
||||
# "check_bkctld" is here as backward compatibility, but is replaced by "check_bkctld_jails"
|
||||
|
@ -72,7 +72,7 @@ command[check_mongodb_connect]={{ nagios_plugins_directory }}/check_mongodb -H l
|
|||
command[check_glusterfs]={{ nagios_plugins_directory }}/check_glusterfs -v all -n 0
|
||||
command[check_supervisord_status]={{ nagios_plugins_directory }}/check_supervisord
|
||||
command[check_varnish]={{ nagios_plugins_directory }}/check_varnish_health -i 127.0.0.1 -p 6082 -s /etc/varnish/secret -w 2 -c 4
|
||||
command[check_haproxy]=sudo {{ nagios_plugins_directory }}/check_haproxy_stats -s /run/haproxy/admin.sock -w 80 -c 90 --ignore-maint --ignore-nolb
|
||||
command[check_haproxy]=sudo {{ nagios_plugins_directory }}/check_haproxy_stats -s /run/haproxy/admin.sock -w 80 -c 90 --ignore-maint --ignore-nolb --ignore-drain
|
||||
command[check_minifirewall]=sudo {{ nagios_plugins_directory }}/check_minifirewall
|
||||
command[check_redis_instances]={{ nagios_plugins_directory }}/check_redis_instances
|
||||
command[check_hpraid]={{ nagios_plugins_directory }}/check_hpraid
|
||||
|
|
|
@ -5,3 +5,5 @@ newrelic_php: False
|
|||
|
||||
newrelic_license: ""
|
||||
newrelic_appname: ""
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -15,7 +15,7 @@
|
|||
- name: Add NewRelic GPG key
|
||||
copy:
|
||||
src: newrelic.asc
|
||||
dest: /etc/apt/trusted.gpg.d/newrelic.asc
|
||||
dest: "{{ apt_keyring_dir }}/newrelic.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
|
@ -23,7 +23,14 @@
|
|||
|
||||
- name: Install NewRelic repository
|
||||
apt_repository:
|
||||
repo: "deb http://apt.newrelic.com/debian/ newrelic non-free"
|
||||
repo: "deb [signed-by={{ apt_keyring_dir }}/newrelic.asc] http://apt.newrelic.com/debian/ newrelic non-free"
|
||||
state: present
|
||||
filename: newrelic
|
||||
update_cache: yes
|
||||
|
||||
- name: Desinstall unsigned NewRelic repository
|
||||
apt_repository:
|
||||
repo: "deb http://apt.newrelic.com/debian/ newrelic non-free"
|
||||
state: absent
|
||||
filename: newrelic
|
||||
update_cache: yes
|
||||
|
|
|
@ -4,3 +4,5 @@
|
|||
nodejs_apt_version: 'node_16.x'
|
||||
|
||||
nodejs_install_yarn: False
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -32,7 +32,7 @@
|
|||
- name: NodeJS GPG key is installed
|
||||
copy:
|
||||
src: nodesource.asc
|
||||
dest: /etc/apt/trusted.gpg.d/nodesource.asc
|
||||
dest: "{{ apt_keyring_dir }}/nodesource.asc"
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
|
@ -43,7 +43,7 @@
|
|||
|
||||
- name: NodeJS sources list ({{ nodejs_apt_version }}) is available
|
||||
apt_repository:
|
||||
repo: "deb https://deb.nodesource.com/{{ nodejs_apt_version }} {{ ansible_distribution_release }} main"
|
||||
repo: "deb [signed-by={{ apt_keyring_dir }}/nodesource.asc] https://deb.nodesource.com/{{ nodejs_apt_version }} {{ ansible_distribution_release }} main"
|
||||
filename: nodesource
|
||||
update_cache: yes
|
||||
state: present
|
||||
|
@ -52,6 +52,17 @@
|
|||
- packages
|
||||
- nodejs
|
||||
|
||||
- name: Unsigned NodeJS sources list ({{ nodejs_apt_version }}) is not available
|
||||
apt_repository:
|
||||
repo: "deb https://deb.nodesource.com/{{ nodejs_apt_version }} {{ ansible_distribution_release }} main"
|
||||
filename: nodesource
|
||||
update_cache: yes
|
||||
state: absent
|
||||
tags:
|
||||
- system
|
||||
- packages
|
||||
- nodejs
|
||||
|
||||
- name: NodeJS is installed
|
||||
apt:
|
||||
name: nodejs
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
- name: Yarn GPG key is installed
|
||||
copy:
|
||||
src: yarn.asc
|
||||
dest: /etc/apt/trusted.gpg.d/yarn.asc
|
||||
dest: "{{ apt_keyring_dir }}/yarn.asc"
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
|
@ -37,7 +37,7 @@
|
|||
|
||||
- name: Yarn sources list is available
|
||||
apt_repository:
|
||||
repo: "deb https://dl.yarnpkg.com/debian/ stable main"
|
||||
repo: "deb [signed-by={{ apt_keyring_dir }}/yarn.asc] https://dl.yarnpkg.com/debian/ stable main"
|
||||
filename: yarn
|
||||
update_cache: yes
|
||||
state: present
|
||||
|
@ -47,6 +47,18 @@
|
|||
- nodejs
|
||||
- yarn
|
||||
|
||||
- name: Unsigned Yarn sources list is not available
|
||||
apt_repository:
|
||||
repo: "deb https://dl.yarnpkg.com/debian/ stable main"
|
||||
filename: yarn
|
||||
update_cache: yes
|
||||
state: absent
|
||||
tags:
|
||||
- system
|
||||
- packages
|
||||
- nodejs
|
||||
- yarn
|
||||
|
||||
- name: Yarn is installed
|
||||
apt:
|
||||
name: yarn
|
||||
|
|
|
@ -1,26 +1,126 @@
|
|||
#!/bin/sh
|
||||
|
||||
carp=$(/sbin/ifconfig carp0 2>/dev/null | grep 'status' | cut -d' ' -f2)
|
||||
VERSION="22.12.1"
|
||||
|
||||
if [ "$carp" = "backup" ]; then
|
||||
exit 0
|
||||
fi
|
||||
show_version() {
|
||||
cat <<END
|
||||
cert-expirations.sh version ${VERSION}
|
||||
|
||||
echo "Warning : all times are in UTC !\n"
|
||||
Copyright 2020-2022 Evolix <info@evolix.fr>,
|
||||
Jérémy Lecour <jlecour@evolix.fr>,
|
||||
Jérémy Dubois <jdubois@evolix.fr>
|
||||
and others.
|
||||
|
||||
echo "CA certificate:"
|
||||
openssl x509 -enddate -noout -in /etc/shellpki/cacert.pem \
|
||||
| cut -d '=' -f 2 \
|
||||
| sed -e "s/^\(.*\)\ \(20..\).*/- \2 \1/"
|
||||
cert-expirations.sh comes with ABSOLUTELY NO WARRANTY. This is free software,
|
||||
and you are welcome to redistribute it under certain conditions.
|
||||
See the MIT Licence for details.
|
||||
END
|
||||
}
|
||||
|
||||
echo ""
|
||||
show_usage() {
|
||||
cat <<END
|
||||
Usage: ${0} [--version]
|
||||
END
|
||||
}
|
||||
|
||||
echo "Client certificates:"
|
||||
cat /etc/shellpki/index.txt \
|
||||
| grep ^V \
|
||||
| awk -F "/" '{print $1,$5}' \
|
||||
| awk '{print $2,$5}' \
|
||||
| sed 's/CN=//' \
|
||||
| sed -E 's/([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2})Z (.*)/- 20\1 \2 \3 \4:\5:\6 \7/' \
|
||||
| awk '{if ($3 == "01") $3="Jan"; else if ($3 == "02") $3="Feb"; else if ($3 == "03") $3="Mar"; else if ($3 == "04") $3="Apr"; else if ($3 == "05") $3="May"; else if ($3 == "06") $3="Jun"; else if ($3 == "07") $3="Jul"; else if ($3 == "08") $3="Aug"; else if ($3 == "09") $3="Sep"; else if ($3 == "10") $3="Oct"; else if ($3 == "11") $3="Nov"; else if ($3 == "12") $3="Dec"; print $0;}' \
|
||||
| sort -n -k 2 -k 3M -k 4
|
||||
check_carp_state() {
|
||||
if [ "${SYSTEM}" = "openbsd" ]; then
|
||||
carp=$(/sbin/ifconfig carp0 2>/dev/null | grep 'status' | cut -d' ' -f2)
|
||||
|
||||
if [ "$carp" = "backup" ]; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
check_ca_expiration() {
|
||||
echo "CA certificate:"
|
||||
openssl x509 -enddate -noout -in ${cacert_path} \
|
||||
| cut -d '=' -f 2 \
|
||||
| sed -e "s/^\(.*\)\ \(20..\).*/- \2 \1/"
|
||||
}
|
||||
|
||||
check_certs_expiration() {
|
||||
# Syntax "cmd | { while read line; do var="foo"; done echo $var }" needed, otherwise $var is empty at the end of while loop
|
||||
grep ^V ${index_path} \
|
||||
| awk -F "/" '{print $1,$5}' \
|
||||
| awk '{print $2,$5}' \
|
||||
| sed 's/CN=//' \
|
||||
| sed -E 's/([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2})Z (.*)/- 20\1 \2 \3 \4:\5:\6 \7/' \
|
||||
| awk '{if ($3 == "01") $3="Jan"; else if ($3 == "02") $3="Feb"; else if ($3 == "03") $3="Mar"; else if ($3 == "04") $3="Apr"; else if ($3 == "05") $3="May"; else if ($3 == "06") $3="Jun"; else if ($3 == "07") $3="Jul"; else if ($3 == "08") $3="Aug"; else if ($3 == "09") $3="Sep"; else if ($3 == "10") $3="Oct"; else if ($3 == "11") $3="Nov"; else if ($3 == "12") $3="Dec"; print $0;}' \
|
||||
| sort -n -k 2 -k 3M -k 4 | {
|
||||
while read -r line; do
|
||||
|
||||
# Predicting expirations - OpenBSD case (date is not the same than in Linux)
|
||||
if [ "${SYSTEM}" = "openbsd" ]; then
|
||||
# Already expired if expiration date is before now
|
||||
if [ "$(TZ=:Zulu date -jf "%Y %b %d %H:%M:%S" "$(echo "$line" | awk '{print $2,$3,$4,$5}')" +%s)" -le "$(date +%s)" ]; then
|
||||
expired_certs="${expired_certs}$line\n"
|
||||
# Expiring soon if expiration date is after now and before now + $somedays days
|
||||
elif [ "$(TZ=:Zulu date -jf "%Y %b %d %H:%M:%S" "$(echo "$line" | awk '{print $2,$3,$4,$5}')" +%s)" -gt "$(date +%s)" ] && [ "$(TZ=:Zulu date -jf "%Y %b %d %H:%M:%S" "$(echo "$line" | awk '{print $2,$3,$4,$5}')" +%s)" -lt "$(($(date +%s) + somedays))" ]; then
|
||||
expiring_soon_certs="${expiring_soon_certs}$line\n"
|
||||
# Still valid for a time if expiration date is after now + $somedays days
|
||||
elif [ "$(TZ=:Zulu date -jf "%Y %b %d %H:%M:%S" "$(echo "$line" | awk '{print $2,$3,$4,$5}')" +%s)" -ge "$(($(date +%s) + somedays))" ]; then
|
||||
still_valid_certs="${still_valid_certs}$line\n"
|
||||
fi
|
||||
# Non OpenBSD cases
|
||||
else
|
||||
# Already expired if expiration date is before now
|
||||
if [ "$(TZ=:Zulu date -d "$(echo "$line" | awk '{print $3,$4,$2,$5}')" +%s)" -le "$(date +%s)" ]; then
|
||||
expired_certs="${expired_certs}$line\n"
|
||||
# Expiring soon if expiration date is after now and before now + $somedays days
|
||||
elif [ "$(TZ=:Zulu date -d "$(echo "$line" | awk '{print $3,$4,$2,$5}')" +%s)" -gt "$(date +%s)" ] && [ "$(TZ=:Zulu date -d "$(echo "$line" | awk '{print $3,$4,$2,$5}')" +%s)" -lt "$(($(date +%s) + somedays))" ]; then
|
||||
expiring_soon_certs="${expiring_soon_certs}$line\n"
|
||||
# Still valid for a time if expiration date is after now + $somedays days
|
||||
elif [ "$(TZ=:Zulu date -d "$(echo "$line" | awk '{print $3,$4,$2,$5}')" +%s)" -ge "$(($(date +%s) + somedays))" ]; then
|
||||
still_valid_certs="${still_valid_certs}$line\n"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Expired client certificates:"
|
||||
echo "${expired_certs}"
|
||||
echo "Valid client certificates expiring soon (in less than $((somedays / 60 / 60 / 24)) days):"
|
||||
echo "${expiring_soon_certs}"
|
||||
echo "Valid client certificates expiring later (in more than $((somedays / 60 / 60 / 24)) days):"
|
||||
echo "${still_valid_certs}"
|
||||
}
|
||||
}
|
||||
|
||||
main() {
|
||||
SYSTEM=$(uname | tr '[:upper:]' '[:lower:]')
|
||||
cacert_path="/etc/shellpki/cacert.pem"
|
||||
index_path="/etc/shellpki/index.txt"
|
||||
somedays="3456000" # 40 days currently
|
||||
expired_certs=""
|
||||
expiring_soon_certs=""
|
||||
still_valid_certs=""
|
||||
|
||||
case "$1" in
|
||||
version|--version)
|
||||
show_version
|
||||
exit 0
|
||||
;;
|
||||
|
||||
help|--help)
|
||||
show_usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
"")
|
||||
check_carp_state
|
||||
echo "Warning : all times are in UTC !"
|
||||
echo ""
|
||||
check_ca_expiration
|
||||
echo ""
|
||||
check_certs_expiration
|
||||
;;
|
||||
|
||||
*)
|
||||
show_usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# VERSION="22.12.2"
|
||||
|
||||
[ ca ]
|
||||
default_ca = CA_default
|
||||
|
||||
|
@ -12,7 +14,7 @@ crl = $dir/crl.pem
|
|||
private_key = $dir/cakey.key
|
||||
RANDFILE = $dir/.rand
|
||||
default_days = 365
|
||||
default_crl_days= 365
|
||||
default_crl_days= 730
|
||||
default_md = sha256
|
||||
preserve = no
|
||||
policy = policy_match
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
set -u
|
||||
|
||||
VERSION="22.04"
|
||||
VERSION="22.12.2"
|
||||
|
||||
show_version() {
|
||||
cat <<END
|
||||
|
@ -137,7 +137,7 @@ warning() {
|
|||
}
|
||||
|
||||
verify_ca_password() {
|
||||
"${OPENSSL_BIN}" rsa \
|
||||
"${OPENSSL_BIN}" pkey \
|
||||
-in "${CA_KEY}" \
|
||||
-passin pass:"${CA_PASSWORD}" \
|
||||
>/dev/null 2>&1
|
||||
|
@ -224,9 +224,10 @@ replace_existing_or_abort() {
|
|||
init() {
|
||||
umask 0177
|
||||
|
||||
[ -d "${CA_DIR}" ] || mkdir -m 0750 "${CA_DIR}"
|
||||
[ -d "${CA_DIR}" ] || mkdir -m 0751 "${CA_DIR}"
|
||||
[ -d "${CRT_DIR}" ] || mkdir -m 0750 "${CRT_DIR}"
|
||||
[ -f "${INDEX_FILE}" ] || touch "${INDEX_FILE}"
|
||||
[ -f "${INDEX_FILE}.attr" ] || touch "${INDEX_FILE}.attr"
|
||||
[ -f "${CRL}" ] || touch "${CRL}"
|
||||
[ -f "${SERIAL}" ] || echo "01" > "${SERIAL}"
|
||||
|
||||
|
@ -278,17 +279,18 @@ init() {
|
|||
|
||||
passout_arg=""
|
||||
if [ -n "${CA_PASSWORD:-}" ]; then
|
||||
passout_arg="-passout pass:${CA_PASSWORD}"
|
||||
passout_arg="-pass pass:${CA_PASSWORD}"
|
||||
elif [ "${non_interactive}" -eq 1 ]; then
|
||||
error "In non-interactive mode, you must pass CA_PASSWORD as environment variable."
|
||||
fi
|
||||
|
||||
if [ ! -f "${CA_KEY}" ]; then
|
||||
"${OPENSSL_BIN}" genrsa \
|
||||
"${OPENSSL_BIN}" genpkey \
|
||||
-algorithm RSA \
|
||||
-out "${CA_KEY}" \
|
||||
${passout_arg} \
|
||||
-aes256 \
|
||||
"${CA_KEY_LENGTH}" \
|
||||
-pkeyopt "rsa_keygen_bits:${CA_KEY_LENGTH}" \
|
||||
>/dev/null 2>&1
|
||||
# shellcheck disable=SC2181
|
||||
if [ "$?" -ne 0 ]; then
|
||||
|
@ -355,9 +357,10 @@ ocsp() {
|
|||
port=$(echo "${ocsp_uri}" | cut -d':' -f2)
|
||||
|
||||
if [ ! -f "${OCSP_KEY}" ]; then
|
||||
"${OPENSSL_BIN}" genrsa \
|
||||
"${OPENSSL_BIN}" genpkey \
|
||||
-algorithm RSA \
|
||||
-out "${OCSP_KEY}" \
|
||||
"${KEY_LENGTH}" \
|
||||
-pkeyopt "rsa_keygen_bits:${KEY_LENGTH}" \
|
||||
>/dev/null 2>&1
|
||||
# shellcheck disable=SC2181
|
||||
if [ "$?" -ne 0 ]; then
|
||||
|
@ -680,17 +683,19 @@ create() {
|
|||
# generate private key
|
||||
pass_args=""
|
||||
if [ -n "${password_file:-}" ]; then
|
||||
pass_args="-aes256 -passout file:${password_file}"
|
||||
pass_args="-aes256 -pass file:${password_file}"
|
||||
elif [ -n "${PASSWORD:-}" ]; then
|
||||
pass_args="-aes256 -passout pass:${PASSWORD}"
|
||||
pass_args="-aes256 -pass pass:${PASSWORD}"
|
||||
fi
|
||||
"${OPENSSL_BIN}" genrsa \
|
||||
"${OPENSSL_BIN}" genpkey \
|
||||
-algorithm RSA \
|
||||
-out "${key_file}" \
|
||||
${pass_args} \
|
||||
"${KEY_LENGTH}" \
|
||||
-pkeyopt "rsa_keygen_bits:${KEY_LENGTH}" \
|
||||
>/dev/null 2>&1
|
||||
# shellcheck disable=SC2181
|
||||
if [ "$?" -eq 0 ]; then
|
||||
chmod 600 "${key_file}"
|
||||
echo "The KEY file is available at \`${key_file}'"
|
||||
else
|
||||
error "Error generating the private key"
|
||||
|
@ -1098,9 +1103,11 @@ main() {
|
|||
|
||||
# fix right
|
||||
chown -R "${PKI_USER}":"${PKI_USER}" "${CA_DIR}"
|
||||
chmod 750 "${CA_DIR}" "${CRT_DIR}" "${KEY_DIR}" "${CSR_DIR}" "${PKCS12_DIR}" "${OVPN_DIR}" "${TMP_DIR}"
|
||||
chmod 600 "${INDEX_FILE}"* "${SERIAL}"* "${CA_KEY}" "${CRL}"
|
||||
chmod 750 "${CRT_DIR}" "${KEY_DIR}" "${CSR_DIR}" "${PKCS12_DIR}" "${OVPN_DIR}" "${TMP_DIR}"
|
||||
chmod 600 "${INDEX_FILE}"* "${SERIAL}"* "${CA_KEY}"
|
||||
chmod 640 "${CA_CERT}"
|
||||
chmod 604 "${CRL}"
|
||||
chmod 751 "${CA_DIR}"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
group: "{{ item.group }}"
|
||||
with_items:
|
||||
- { source: "openssl.cnf", destination: "/etc/shellpki/openssl.cnf", mode: "0640", owner: "shellpki", group: "shellpki" }
|
||||
- { source: "shellpki", destination: "/usr/local/sbin/shellpki", mode: "0755", owner: "root", group: "root" }
|
||||
- { source: "shellpki", destination: "/usr/local/sbin/shellpki", mode: "0750", owner: "root", group: "root" }
|
||||
|
||||
- name: Add sudo rights
|
||||
lineinfile:
|
||||
|
@ -77,16 +77,6 @@
|
|||
- include_role:
|
||||
name: evolix/remount-usr
|
||||
|
||||
- name: Fix CRL rights in shellpki command
|
||||
lineinfile:
|
||||
dest: "/usr/local/sbin/shellpki"
|
||||
regexp: '{{ item.regexp }}'
|
||||
insertafter: "{{ item.insertafter }}"
|
||||
line: "{{ item.line }}"
|
||||
with_items:
|
||||
- { regexp: '^ chmod 604 /etc/shellpki/crl.pem$', line: " chmod 604 /etc/shellpki/crl.pem", insertafter: '^ chmod 640 "\${CACERT}"$' }
|
||||
- { regexp: '^ chmod 751 /etc/shellpki/$', line: " chmod 751 /etc/shellpki/", insertafter: '^ chmod 604 /etc/shellpki/crl.pem$' }
|
||||
|
||||
- name: Deploy OpenVPN server config
|
||||
template:
|
||||
src: "server.conf.j2"
|
||||
|
@ -261,7 +251,7 @@
|
|||
cron:
|
||||
name: "OpenVPN certificates expiration"
|
||||
special_time: monthly
|
||||
job: '/usr/share/scripts/cert-expirations.sh | mail -E -s "PKI VPN {{ ansible_hostname }} : recapitulatif expirations" {{ client_email }}'
|
||||
job: '/usr/share/scripts/cert-expirations.sh | mail -E -s "PKI OpenVPN {{ ansible_hostname }} : recapitulatif expirations" {{ client_email }}'
|
||||
|
||||
- name: Generate the CA password
|
||||
set_fact:
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
group: "{{ item.group }}"
|
||||
with_items:
|
||||
- { source: "openssl.cnf", destination: "/etc/shellpki/openssl.cnf", mode: "0640", owner: "_shellpki", group: "_shellpki" }
|
||||
- { source: "shellpki", destination: "/usr/local/sbin/shellpki", mode: "0755", owner: "root", group: "wheel" }
|
||||
- { source: "shellpki", destination: "/usr/local/sbin/shellpki", mode: "0750", owner: "root", group: "wheel" }
|
||||
|
||||
- name: Add sudo rights
|
||||
lineinfile:
|
||||
|
@ -60,16 +60,6 @@
|
|||
path: /etc/shellpki/dh2048.pem
|
||||
size: 2048
|
||||
|
||||
- name: Fix CRL rights in shellpki command
|
||||
lineinfile:
|
||||
dest: "/usr/local/sbin/shellpki"
|
||||
regexp: '{{ item.regexp }}'
|
||||
insertafter: "{{ item.insertafter }}"
|
||||
line: "{{ item.line }}"
|
||||
with_items:
|
||||
- { regexp: '^ chmod 604 /etc/shellpki/crl.pem$', line: " chmod 604 /etc/shellpki/crl.pem", insertafter: '^ chmod 640 "\${CACERT}"$' }
|
||||
- { regexp: '^ chmod 751 /etc/shellpki/$', line: " chmod 751 /etc/shellpki/", insertafter: '^ chmod 604 /etc/shellpki/crl.pem$' }
|
||||
|
||||
- name: Deploy OpenVPN server config
|
||||
template:
|
||||
src: "server.conf.j2"
|
||||
|
@ -189,7 +179,7 @@
|
|||
cron:
|
||||
name: "OpenVPN certificates expiration"
|
||||
special_time: monthly
|
||||
job: '/usr/share/scripts/cert-expirations.sh | mail -E -s "PKI VPN {{ ansible_hostname }} : recapitulatif expirations" {{ client_email }}'
|
||||
job: '/usr/share/scripts/cert-expirations.sh | mail -E -s "PKI OpenVPN {{ ansible_hostname }} : recapitulatif expirations" {{ client_email }}'
|
||||
|
||||
- name: Generate the CA password
|
||||
set_fact:
|
||||
|
|
|
@ -26,18 +26,5 @@ galaxy_info:
|
|||
|
||||
allow_duplicates: true
|
||||
|
||||
dependencies:
|
||||
- { role: evolix/apache }
|
||||
- { role: evolix/php, php_apache_enable: True, when: packweb_apache_modphp }
|
||||
- { role: evolix/php, php_fpm_enable: True, when: packweb_apache_fpm }
|
||||
- { role: evolix/squid, squid_localproxy_enable: True }
|
||||
- { role: evolix/mysql, when: packweb_mysql_variant == "debian" }
|
||||
- { role: evolix/mysql-oracle, when: packweb_mysql_variant == "oracle" }
|
||||
- { role: evolix/lxc-php, lxc_php_version: php56, lxc_php_create_mysql_link: True, when: "'php56' in packweb_multiphp_versions" }
|
||||
- { role: evolix/lxc-php, lxc_php_version: php70, lxc_php_create_mysql_link: True, when: "'php70' in packweb_multiphp_versions" }
|
||||
- { role: evolix/lxc-php, lxc_php_version: php73, lxc_php_create_mysql_link: True, when: "'php73' in packweb_multiphp_versions" }
|
||||
- { role: evolix/lxc-php, lxc_php_version: php74, lxc_php_create_mysql_link: True, when: "'php74' in packweb_multiphp_versions" }
|
||||
- { role: evolix/lxc-php, lxc_php_version: php80, lxc_php_create_mysql_link: True, when: "'php80' in packweb_multiphp_versions" }
|
||||
- { role: evolix/lxc-php, lxc_php_version: php81, lxc_php_create_mysql_link: True, when: "'php81' in packweb_multiphp_versions" }
|
||||
- { role: evolix/webapps/evoadmin-web, evoadmin_enable_vhost: "{{ packweb_enable_evoadmin_vhost }}", evoadmin_multiphp_versions: "{{ packweb_multiphp_versions }}" }
|
||||
- { role: evolix/evoacme }
|
||||
dependencies: []
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
- include
|
||||
- negotiation
|
||||
- alias
|
||||
- log_forensic
|
||||
|
||||
- name: Copy Apache settings for modules
|
||||
copy:
|
||||
|
|
80
packweb-apache/tasks/dependencies.yml
Normal file
80
packweb-apache/tasks/dependencies.yml
Normal file
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
|
||||
- import_role:
|
||||
name: evolix/apache
|
||||
|
||||
- import_role:
|
||||
name: evolix/php
|
||||
vars:
|
||||
php_apache_enable: True
|
||||
when: packweb_apache_modphp
|
||||
|
||||
- import_role:
|
||||
name: evolix/php
|
||||
vars:
|
||||
php_fpm_enable: True
|
||||
when: packweb_apache_fpm
|
||||
|
||||
- import_role:
|
||||
name: evolix/squid
|
||||
vars:
|
||||
squid_localproxy_enable: True
|
||||
|
||||
- import_role:
|
||||
name: evolix/mysql
|
||||
when: packweb_mysql_variant == "debian"
|
||||
|
||||
- import_role:
|
||||
name: evolix/mysql-oracle
|
||||
when: packweb_mysql_variant == "oracle"
|
||||
|
||||
- import_role:
|
||||
name: evolix/lxc-php
|
||||
vars:
|
||||
lxc_php_version: php56
|
||||
lxc_php_create_mysql_link: True
|
||||
when: "'php56' in packweb_multiphp_versions"
|
||||
|
||||
- import_role:
|
||||
name: evolix/lxc-php
|
||||
vars:
|
||||
lxc_php_version: php70
|
||||
lxc_php_create_mysql_link: True
|
||||
when: "'php70' in packweb_multiphp_versions"
|
||||
|
||||
- import_role:
|
||||
name: evolix/lxc-php
|
||||
vars:
|
||||
lxc_php_version: php73
|
||||
lxc_php_create_mysql_link: True
|
||||
when: "'php73' in packweb_multiphp_versions"
|
||||
|
||||
- import_role:
|
||||
name: evolix/lxc-php
|
||||
vars:
|
||||
lxc_php_version: php74
|
||||
lxc_php_create_mysql_link: True
|
||||
when: "'php74' in packweb_multiphp_versions"
|
||||
|
||||
- import_role:
|
||||
name: evolix/lxc-php
|
||||
vars:
|
||||
lxc_php_version: php80
|
||||
lxc_php_create_mysql_link: True
|
||||
when: "'php80' in packweb_multiphp_versions"
|
||||
|
||||
- import_role:
|
||||
name: evolix/lxc-php
|
||||
vars:
|
||||
lxc_php_version: php81
|
||||
lxc_php_create_mysql_link: True
|
||||
when: "'php81' in packweb_multiphp_versions"
|
||||
|
||||
- import_role:
|
||||
name: evolix/webapps/evoadmin-web
|
||||
vars:
|
||||
evoadmin_enable_vhost: "{{ packweb_enable_evoadmin_vhost }}"
|
||||
evoadmin_multiphp_versions: "{{ packweb_multiphp_versions }}"
|
||||
|
||||
- import_role:
|
||||
name: evolix/evoacme
|
|
@ -1,5 +1,8 @@
|
|||
---
|
||||
|
||||
- name: Dependencies are satisfied
|
||||
include_tasks: dependencies.yml
|
||||
|
||||
- fail:
|
||||
msg: only compatible with Debian >= 8
|
||||
when:
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
- name: "Met-à-jour userlogrotate"
|
||||
ansible.builtin.copy:
|
||||
src: userlogrotate
|
||||
dest: "{{ item }}"
|
||||
dest: "{{ item }}"
|
||||
mode: "0755"
|
||||
loop: "{{ find_logrotate.files }}"
|
||||
when: find_logrotate.files | length>0
|
||||
|
|
|
@ -2,3 +2,5 @@
|
|||
|
||||
percona__install_xtrabackup: True
|
||||
percona__xtrabackup_package_name: percona-xtrabackup-24
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -18,7 +18,7 @@
|
|||
- name: Add Percona GPG key
|
||||
copy:
|
||||
src: percona.asc
|
||||
dest: /etc/apt/trusted.gpg.d/percona.asc
|
||||
dest: "{{ apt_keyring_dir }}/percona.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
|
|
|
@ -8,3 +8,5 @@ php_symfony_requirements: False
|
|||
php_modules_mysqlnd: False
|
||||
|
||||
php_fpm_remove_default_pool: False
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
|
@ -19,3 +19,8 @@
|
|||
service:
|
||||
name: php7.4-fpm
|
||||
state: restarted
|
||||
|
||||
- name: restart php8.1-fpm
|
||||
service:
|
||||
name: php8.1-fpm
|
||||
state: restarted
|
||||
|
|
|
@ -4,17 +4,20 @@
|
|||
that:
|
||||
- ansible_distribution == "Debian"
|
||||
- ansible_distribution_major_version is version('8', '>=')
|
||||
- ansible_distribution_major_version is version('11', '<=')
|
||||
msg: This is only compatible with Debian 8 → 11
|
||||
- ansible_distribution_major_version is version('12', '<=')
|
||||
msg: This is only compatible with Debian 8 → 12
|
||||
|
||||
- include: main_jessie.yml
|
||||
- include_tasks: main_jessie.yml
|
||||
when: ansible_distribution_release == "jessie"
|
||||
|
||||
- include: main_stretch.yml
|
||||
- include_tasks: main_stretch.yml
|
||||
when: ansible_distribution_release == "stretch"
|
||||
|
||||
- include: main_buster.yml
|
||||
- include_tasks: main_buster.yml
|
||||
when: ansible_distribution_release == "buster"
|
||||
|
||||
- include: main_bullseye.yml
|
||||
- include_tasks: main_bullseye.yml
|
||||
when: ansible_distribution_release == "bullseye"
|
||||
|
||||
- include_tasks: main_bookworm.yml
|
||||
when: ansible_distribution_release == "bookworm"
|
||||
|
|
108
php/tasks/main_bookworm.yml
Normal file
108
php/tasks/main_bookworm.yml
Normal file
|
@ -0,0 +1,108 @@
|
|||
---
|
||||
|
||||
- name: "Set php version to 8.1 (Debian 12)"
|
||||
set_fact:
|
||||
php_version: "8.1"
|
||||
|
||||
- name: "Set php config directories (Debian 12)"
|
||||
set_fact:
|
||||
php_cli_conf_dir: "/etc/php/{{ php_version }}/cli/conf.d"
|
||||
php_apache_conf_dir: "/etc/php/{{ php_version }}/apache2/conf.d"
|
||||
php_fpm_conf_dir: "/etc/php/{{ php_version }}/fpm/conf.d"
|
||||
php_fpm_pool_dir: "/etc/php/{{ php_version }}/fpm/pool.d"
|
||||
|
||||
- name: "Set php config files (Debian 12)"
|
||||
set_fact:
|
||||
php_cli_defaults_ini_file: "{{ php_cli_conf_dir }}/z-evolinux-defaults.ini"
|
||||
php_cli_custom_ini_file: "{{ php_cli_conf_dir }}/zzz-evolinux-custom.ini"
|
||||
php_apache_defaults_ini_file: "{{ php_apache_conf_dir }}/z-evolinux-defaults.ini"
|
||||
php_apache_custom_ini_file: "{{ php_apache_conf_dir }}/zzz-evolinux-custom.ini"
|
||||
php_fpm_defaults_ini_file: "{{ php_fpm_conf_dir }}/z-evolinux-defaults.ini"
|
||||
php_fpm_custom_ini_file: "{{ php_fpm_conf_dir }}/zzz-evolinux-custom.ini"
|
||||
php_fpm_debian_default_pool_file: "{{ php_fpm_pool_dir}}/www.conf"
|
||||
php_fpm_default_pool_file: "{{ php_fpm_pool_dir}}/www-evolinux-defaults.conf"
|
||||
php_fpm_default_pool_custom_file: "{{ php_fpm_pool_dir}}/www-evolinux-zcustom.conf"
|
||||
php_fpm_default_pool_socket: "/var/run/php/php{{ php_version }}-fpm.sock"
|
||||
php_fpm_service_name: "php{{ php_version }}-fpm"
|
||||
|
||||
# Packages
|
||||
|
||||
- name: "Set package list (Debian 12)"
|
||||
set_fact:
|
||||
php_stretch_packages:
|
||||
- php-cli
|
||||
- php-gd
|
||||
- php-intl
|
||||
- php-imap
|
||||
- php-ldap
|
||||
- php-mysql
|
||||
# php-mcrypt is no longer packaged for PHP 7.2
|
||||
- php-pgsql
|
||||
- php-sqlite3
|
||||
- php-curl
|
||||
- php-ssh2
|
||||
- php-xml
|
||||
- php-zip
|
||||
- composer
|
||||
- libphp-phpmailer
|
||||
|
||||
- include: sury_pre.yml
|
||||
when: php_sury_enable
|
||||
|
||||
- name: "Install PHP packages (Debian 12)"
|
||||
apt:
|
||||
name: '{{ php_stretch_packages }}'
|
||||
state: present
|
||||
|
||||
- name: "Install mod_php packages (Debian 12)"
|
||||
apt:
|
||||
name:
|
||||
- libapache2-mod-php
|
||||
- php
|
||||
state: present
|
||||
when: php_apache_enable
|
||||
|
||||
- name: "Install PHP FPM packages (Debian 12)"
|
||||
apt:
|
||||
name:
|
||||
- php-fpm
|
||||
- php
|
||||
state: present
|
||||
when: php_fpm_enable
|
||||
|
||||
# Configuration
|
||||
|
||||
- name: "Enforce permissions on PHP directory (Debian 12)"
|
||||
file:
|
||||
dest: "{{ item }}"
|
||||
mode: "0755"
|
||||
with_items:
|
||||
- /etc/php
|
||||
- /etc/php/{{ php_version }}
|
||||
|
||||
- include: config_cli.yml
|
||||
- name: "Enforce permissions on PHP cli directory (Debian 12)"
|
||||
file:
|
||||
dest: /etc/php/{{ php_version }}/cli
|
||||
mode: "0755"
|
||||
|
||||
- include: config_fpm.yml
|
||||
when: php_fpm_enable
|
||||
|
||||
- name: "Enforce permissions on PHP fpm directory (Debian 12)"
|
||||
file:
|
||||
dest: /etc/php/{{ php_version }}/fpm
|
||||
mode: "0755"
|
||||
when: php_fpm_enable
|
||||
|
||||
- include: config_apache.yml
|
||||
when: php_apache_enable
|
||||
|
||||
- name: "Enforce permissions on PHP apache2 directory (Debian 12)"
|
||||
file:
|
||||
dest: /etc/php/{{ php_version }}/apache2
|
||||
mode: "0755"
|
||||
when: php_apache_enable
|
||||
|
||||
- include: sury_post.yml
|
||||
when: php_sury_enable
|
|
@ -3,7 +3,7 @@
|
|||
- name: Setup deb.sury.org repository - Add GPG key
|
||||
copy:
|
||||
src: sury.gpg
|
||||
dest: /etc/apt/trusted.gpg.d/sury.gpg
|
||||
dest: "{{ apt_keyring_dir }}/sury.gpg"
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
|
@ -20,10 +20,16 @@
|
|||
|
||||
- name: Setup deb.sury.org repository - Add source list
|
||||
apt_repository:
|
||||
repo: "deb https://packages.sury.org/php/ {{ ansible_distribution_release }} main"
|
||||
repo: "deb [signed-by={{ apt_keyring_dir }}/sury.gpg] https://packages.sury.org/php/ {{ ansible_distribution_release }} main"
|
||||
filename: sury
|
||||
state: present
|
||||
|
||||
- name: Setup deb.sury.org repository - Remove unsigned source list
|
||||
apt_repository:
|
||||
repo: "deb https://packages.sury.org/php/ {{ ansible_distribution_release }} main"
|
||||
filename: sury
|
||||
state: absent
|
||||
|
||||
- name: "Override package list for Sury (Debian 9 or later)"
|
||||
set_fact:
|
||||
php_stretch_packages:
|
||||
|
|
|
@ -20,3 +20,5 @@ locales_default: fr_FR.UTF-8
|
|||
|
||||
# PostGIS
|
||||
postgresql_install_postgis: False
|
||||
|
||||
apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}"
|
16
postgresql/tasks/packages_bookworm.yml
Normal file
16
postgresql/tasks/packages_bookworm.yml
Normal file
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
|
||||
- name: "Set variables (Debian 12)"
|
||||
set_fact:
|
||||
postgresql_version: '15'
|
||||
when: postgresql_version is none or postgresql_version | length == 0
|
||||
|
||||
- include: pgdg-repo.yml
|
||||
when: postgresql_version != '15'
|
||||
|
||||
- name: Install postgresql package
|
||||
apt:
|
||||
name:
|
||||
- "postgresql-{{postgresql_version}}"
|
||||
- pgtop
|
||||
- libdbd-pg-perl
|
|
@ -23,16 +23,22 @@
|
|||
- name: Add PGDG GPG key
|
||||
copy:
|
||||
src: postgresql.asc
|
||||
dest: /etc/apt/trusted.gpg.d/postgresql.asc
|
||||
dest: "{{ apt_keyring_dir }}/postgresql.asc"
|
||||
force: yes
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: Add PGDG repository
|
||||
apt_repository:
|
||||
repo: "deb [signed-by={{ apt_keyring_dir }}/postgresql.asc] http://apt.postgresql.org/pub/repos/apt/ {{ansible_distribution_release}}-pgdg main"
|
||||
update_cache: yes
|
||||
|
||||
- name: Remove unsigned PGDG repository
|
||||
apt_repository:
|
||||
repo: "deb http://apt.postgresql.org/pub/repos/apt/ {{ansible_distribution_release}}-pgdg main"
|
||||
update_cache: yes
|
||||
state: absent
|
||||
|
||||
- name: Add APT preference file
|
||||
template:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue