Merge branch 'unstable' into stable
gitea/ansible-roles/pipeline/head This commit looks good Details
gitea/ansible-roles/pipeline/tag This commit looks good Details

This commit is contained in:
Jérémy Lecour 2022-09-19 17:06:57 +02:00 committed by Jérémy Lecour
commit c3670ce897
67 changed files with 1632 additions and 905 deletions

View File

@ -21,11 +21,11 @@ pipeline {
def major = versions[0] def major = versions[0]
def minor = versions[0] + '.' + versions[1] def minor = versions[0] + '.' + versions[1]
def patch = version.trim() def patch = version.trim()
/* No crendentials yet docker.withRegistry('', 'hub.docker') {
im.push(major) im.push(major)
im.push(minor) im.push(minor)
im.push(patch) im.push(patch)
*/ }
} }
} }
} }
@ -40,9 +40,9 @@ pipeline {
im.inside { im.inside {
sh 'echo Test needed' sh 'echo Test needed'
} }
/* No crendentials yet docker.withRegistry('', 'hub.docker') {
im.push('latest') im.push('latest')
*/ }
} }
} }
} }

View File

@ -1,36 +0,0 @@
kind: pipeline
name: default
steps:
- name: build tagged docker image
image: plugins/docker
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
dockerfile: Dockerfile
repo: evolix/ansible-roles
auto_tag: true
environment:
ROLES_VERSION: $DRONE_COMMIT_SHA
when:
event:
- tag
- name: build latest docker image
image: plugins/docker
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
dockerfile: Dockerfile
repo: evolix/ansible-roles
tags: latest
environment:
ROLES_VERSION: $DRONE_COMMIT_SHA
when:
branch:
- unstable

View File

@ -20,6 +20,45 @@ The **patch** part changes is incremented if multiple releases happen the same m
### Security ### Security
## [22.09] 2022-09-19
### Added
* evolinux_users: create only users who have a certain value for the `create` key (default: `always`).
* php: install php-xml with recent PHP versions
* vrrp: add an `ip.yml` task file to help create VRRP addresses
* webapps/nextcloud: Add compatibility with apache2, and apache2 mod_php.
* memcached: NRPE check for multi-instance setup
* munin: Add ipmi_ plugins on dedicated hardware
* proftpd: Add options to override configs (and add a warning if file was overriden)
* proftpd: Allow user auth with ssh keys
### Changed
* evocheck: upstream release 22.09
* evolinux-base: update-evobackup-canary upstream release 22.06
* generate-ldif: Support any MariaDB version
* minifirewall: use handlers to restart minifirewall
* openvpn: automate the initialization of the CA and the creation of the server certificate ; use openssl_dhparam module instead of a command
* generate-ldif: support any version of MariaDB (instead of only 10.0, 10.1 and 10.3)
* openvpn: Run OpenVPN with the \_openvpn user and group instead of nobody which is originally for NFS
* nagios-nrpe: Upgrade check_mongo
### Fixed
* fail2ban: fix dovecot-evolix regex syntax
* haproxy: make it so that munin doesn't break if there is a non default `haproxy_stats_path`
* mysql: Add missing Munin conf for Debian 11
* redis: config directory must be owned by the user that runs the service (to be able to write tmp config files in it)
* varnish: make `-j <jail_config>` the first argument on jessie/stretch as it has to be the first argument there.
* webapps/nextcloud: Add missing dependencies for imagick
### Removed
* evocheck: remove failure if deprecated variable is used
* webapps/nextcloud: Drop support for Nginx
## [22.07.1] 2022-07-28 ## [22.07.1] 2022-07-28
### Changed ### Changed

View File

@ -1,10 +1,10 @@
#!/bin/bash #!/bin/bash
# EvoCheck # EvoCheck
# Script to verify compliance of a Debian/OpenBSD server # Script to verify compliance of a Linux (Debian) server
# powered by Evolix # powered by Evolix
VERSION="22.07" VERSION="22.09"
readonly VERSION readonly VERSION
# base functions # base functions
@ -30,7 +30,7 @@ END
} }
show_help() { show_help() {
cat <<END cat <<END
evocheck is a script that verifies Evolix conventions on Debian/OpenBSD servers. evocheck is a script that verifies Evolix conventions on Linux (Debian) servers.
Usage: evocheck Usage: evocheck
or evocheck --cron or evocheck --cron
@ -50,7 +50,6 @@ detect_os() {
# OS detection # OS detection
DEBIAN_RELEASE="" DEBIAN_RELEASE=""
LSB_RELEASE_BIN=$(command -v lsb_release) LSB_RELEASE_BIN=$(command -v lsb_release)
OPENBSD_RELEASE=""
if [ -e /etc/debian_version ]; then if [ -e /etc/debian_version ]; then
DEBIAN_VERSION=$(cut -d "." -f 1 < /etc/debian_version) DEBIAN_VERSION=$(cut -d "." -f 1 < /etc/debian_version)
@ -68,9 +67,6 @@ detect_os() {
12) DEBIAN_RELEASE="bookworm";; 12) DEBIAN_RELEASE="bookworm";;
esac esac
fi fi
elif [ "$(uname -s)" = "OpenBSD" ]; then
# use a better release name
OPENBSD_RELEASE=$(uname -r)
fi fi
} }
@ -107,9 +103,6 @@ debian_release() {
debian_version() { debian_version() {
printf "%s" "${DEBIAN_VERSION}" printf "%s" "${DEBIAN_VERSION}"
} }
is_openbsd() {
test -n "${OPENBSD_RELEASE}"
}
is_pack_web(){ is_pack_web(){
test -e /usr/share/scripts/web-add.sh || test -e /usr/share/scripts/evoadmin/web-add.sh test -e /usr/share/scripts/web-add.sh || test -e /usr/share/scripts/evoadmin/web-add.sh
@ -582,8 +575,8 @@ 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" " ") 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 fi
for interface in $interfaces; do for interface in $interfaces; do
if ! grep -q "^auto $interface" /etc/network/interfaces; then if grep -Rq "^iface $interface" /etc/network/interfaces* && ! grep -Rq "^auto $interface" /etc/network/interfaces*; then
failed "IS_AUTOIF" "Network interface \`${interface}' is not set to auto" failed "IS_AUTOIF" "Network interface \`${interface}' is statically defined but not set to auto"
test "${VERBOSE}" = 1 || break test "${VERBOSE}" = 1 || break
fi fi
done done
@ -1226,18 +1219,18 @@ check_usrsharescripts() {
check_sshpermitrootno() { check_sshpermitrootno() {
sshd_args="-C addr=,user=,host=,laddr=,lport=0" sshd_args="-C addr=,user=,host=,laddr=,lport=0"
if is_debian_jessie || is_debian_stretch; then if is_debian_jessie || is_debian_stretch; then
# Noop, we'll use the default $sshd_args # Noop, we'll use the default $sshd_args
: :
elif is_debian_buster; then elif is_debian_buster; then
sshd_args="${sshd_args},rdomain=" sshd_args="${sshd_args},rdomain="
else else
# NOTE: From Debian Bullseye 11 onward, with OpenSSH 8.1, the argument # NOTE: From Debian Bullseye 11 onward, with OpenSSH 8.1, the argument
# -T doesn't require the additional -C. # -T doesn't require the additional -C.
sshd_args= sshd_args=
fi fi
# shellcheck disable=SC2086 # shellcheck disable=SC2086
if ! (sshd -T ${sshd_args} | grep -q 'permitrootlogin no'); then if ! (sshd -T ${sshd_args} 2> /dev/null | grep -qi 'permitrootlogin no'); then
failed "IS_SSHPERMITROOTNO" "PermitRoot should be set to no" failed "IS_SSHPERMITROOTNO" "PermitRoot should be set to no"
fi fi
} }
check_evomaintenanceusers() { check_evomaintenanceusers() {
@ -1408,8 +1401,6 @@ download_versions() {
if is_debian; then if is_debian; then
versions_url="https://upgrades.evolix.org/versions-${DEBIAN_RELEASE}" versions_url="https://upgrades.evolix.org/versions-${DEBIAN_RELEASE}"
elif is_openbsd; then
versions_url="https://upgrades.evolix.org/versions-${OPENBSD_RELEASE}"
else else
failed "IS_CHECK_VERSIONS" "error determining os release" failed "IS_CHECK_VERSIONS" "error determining os release"
fi fi
@ -1536,9 +1527,7 @@ main() {
main_output_file=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.main.XXXXX") main_output_file=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.main.XXXXX")
files_to_cleanup="${files_to_cleanup} ${main_output_file}" files_to_cleanup="${files_to_cleanup} ${main_output_file}"
#----------------------------------------------------------- MINIFW_FILE=$(minifirewall_file)
# Tests communs à tous les systèmes
#-----------------------------------------------------------
test "${IS_TMP_1777:=1}" = 1 && check_tmp_1777 test "${IS_TMP_1777:=1}" = 1 && check_tmp_1777
test "${IS_ROOT_0700:=1}" = 1 && check_root_0700 test "${IS_ROOT_0700:=1}" = 1 && check_root_0700
@ -1549,221 +1538,111 @@ main() {
test "${IS_EVOMAINTENANCECONF:=1}" = 1 && check_evomaintenanceconf test "${IS_EVOMAINTENANCECONF:=1}" = 1 && check_evomaintenanceconf
test "${IS_PRIVKEYWOLRDREADABLE:=1}" = 1 && check_privatekeyworldreadable test "${IS_PRIVKEYWOLRDREADABLE:=1}" = 1 && check_privatekeyworldreadable
#----------------------------------------------------------- test "${IS_LSBRELEASE:=1}" = 1 && check_lsbrelease
# Vérifie si c'est une debian et fait les tests appropriés. test "${IS_DPKGWARNING:=1}" = 1 && check_dpkgwarning
#----------------------------------------------------------- test "${IS_UMASKSUDOERS:=1}" = 1 && check_umasksudoers
test "${IS_NRPEPOSTFIX:=1}" = 1 && check_nrpepostfix
if is_debian; then test "${IS_MODSECURITY:=1}" = 1 && check_modsecurity
MINIFW_FILE=$(minifirewall_file) test "${IS_CUSTOMSUDOERS:=1}" = 1 && check_customsudoers
test "${IS_VARTMPFS:=1}" = 1 && check_vartmpfs
test "${IS_LSBRELEASE:=1}" = 1 && check_lsbrelease test "${IS_SERVEURBASE:=1}" = 1 && check_serveurbase
test "${IS_DPKGWARNING:=1}" = 1 && check_dpkgwarning test "${IS_LOGROTATECONF:=1}" = 1 && check_logrotateconf
test "${IS_UMASKSUDOERS:=1}" = 1 && check_umasksudoers test "${IS_SYSLOGCONF:=1}" = 1 && check_syslogconf
test "${IS_NRPEPOSTFIX:=1}" = 1 && check_nrpepostfix test "${IS_DEBIANSECURITY:=1}" = 1 && check_debiansecurity
test "${IS_MODSECURITY:=1}" = 1 && check_modsecurity test "${IS_APTITUDEONLY:=1}" = 1 && check_aptitudeonly
test "${IS_CUSTOMSUDOERS:=1}" = 1 && check_customsudoers test "${IS_APTITUDE:=1}" = 1 && check_aptitude
test "${IS_VARTMPFS:=1}" = 1 && check_vartmpfs test "${IS_APTGETBAK:=1}" = 1 && check_aptgetbak
test "${IS_SERVEURBASE:=1}" = 1 && check_serveurbase test "${IS_APTICRON:=0}" = 1 && check_apticron
test "${IS_LOGROTATECONF:=1}" = 1 && check_logrotateconf test "${IS_USRRO:=1}" = 1 && check_usrro
test "${IS_SYSLOGCONF:=1}" = 1 && check_syslogconf test "${IS_TMPNOEXEC:=1}" = 1 && check_tmpnoexec
test "${IS_DEBIANSECURITY:=1}" = 1 && check_debiansecurity test "${IS_MOUNT_FSTAB:=1}" = 1 && check_mountfstab
test "${IS_APTITUDEONLY:=1}" = 1 && check_aptitudeonly test "${IS_LISTCHANGESCONF:=1}" = 1 && check_listchangesconf
test "${IS_APTITUDE:=1}" = 1 && check_aptitude test "${IS_CUSTOMCRONTAB:=1}" = 1 && check_customcrontab
test "${IS_APTGETBAK:=1}" = 1 && check_aptgetbak test "${IS_SSHALLOWUSERS:=1}" = 1 && check_sshallowusers
test "${IS_APTICRON:=0}" = 1 && check_apticron test "${IS_DISKPERF:=0}" = 1 && check_diskperf
test "${IS_USRRO:=1}" = 1 && check_usrro test "${IS_TMOUTPROFILE:=1}" = 1 && check_tmoutprofile
test "${IS_TMPNOEXEC:=1}" = 1 && check_tmpnoexec test "${IS_ALERT5BOOT:=1}" = 1 && check_alert5boot
test "${IS_MOUNT_FSTAB:=1}" = 1 && check_mountfstab test "${IS_ALERT5MINIFW:=1}" = 1 && check_alert5minifw
test "${IS_LISTCHANGESCONF:=1}" = 1 && check_listchangesconf test "${IS_ALERT5MINIFW:=1}" = 1 && test "${IS_MINIFW:=1}" = 1 && check_minifw
test "${IS_CUSTOMCRONTAB:=1}" = 1 && check_customcrontab test "${IS_NRPEPERMS:=1}" = 1 && check_nrpeperms
test "${IS_SSHALLOWUSERS:=1}" = 1 && check_sshallowusers test "${IS_MINIFWPERMS:=1}" = 1 && check_minifwperms
test "${IS_DISKPERF:=0}" = 1 && check_diskperf # Enable when minifirewall is released
test "${IS_TMOUTPROFILE:=1}" = 1 && check_tmoutprofile test "${IS_MINIFWINCLUDES:=0}" = 1 && check_minifw_includes
test "${IS_ALERT5BOOT:=1}" = 1 && check_alert5boot test "${IS_NRPEDISKS:=0}" = 1 && check_nrpedisks
test "${IS_ALERT5MINIFW:=1}" = 1 && check_alert5minifw test "${IS_NRPEPID:=1}" = 1 && check_nrpepid
test "${IS_ALERT5MINIFW:=1}" = 1 && test "${IS_MINIFW:=1}" = 1 && check_minifw test "${IS_GRSECPROCS:=1}" = 1 && check_grsecprocs
test "${IS_NRPEPERMS:=1}" = 1 && check_nrpeperms test "${IS_APACHEMUNIN:=1}" = 1 && check_apachemunin
test "${IS_MINIFWPERMS:=1}" = 1 && check_minifwperms test "${IS_MYSQLUTILS:=1}" = 1 && check_mysqlutils
# Enable when minifirewall is released test "${IS_RAIDSOFT:=1}" = 1 && check_raidsoft
test "${IS_MINIFWINCLUDES:=0}" = 1 && check_minifw_includes test "${IS_AWSTATSLOGFORMAT:=1}" = 1 && check_awstatslogformat
test "${IS_NRPEDISKS:=0}" = 1 && check_nrpedisks test "${IS_MUNINLOGROTATE:=1}" = 1 && check_muninlogrotate
test "${IS_NRPEPID:=1}" = 1 && check_nrpepid test "${IS_SQUID:=1}" = 1 && check_squid
test "${IS_GRSECPROCS:=1}" = 1 && check_grsecprocs test "${IS_EVOMAINTENANCE_FW:=1}" = 1 && check_evomaintenance_fw
test "${IS_APACHEMUNIN:=1}" = 1 && check_apachemunin test "${IS_MODDEFLATE:=1}" = 1 && check_moddeflate
test "${IS_MYSQLUTILS:=1}" = 1 && check_mysqlutils test "${IS_LOG2MAILRUNNING:=1}" = 1 && check_log2mailrunning
test "${IS_RAIDSOFT:=1}" = 1 && check_raidsoft test "${IS_LOG2MAILAPACHE:=1}" = 1 && check_log2mailapache
test "${IS_AWSTATSLOGFORMAT:=1}" = 1 && check_awstatslogformat test "${IS_LOG2MAILMYSQL:=1}" = 1 && check_log2mailmysql
test "${IS_MUNINLOGROTATE:=1}" = 1 && check_muninlogrotate test "${IS_LOG2MAILSQUID:=1}" = 1 && check_log2mailsquid
test "${IS_SQUID:=1}" = 1 && check_squid test "${IS_BINDCHROOT:=1}" = 1 && check_bindchroot
test "${IS_EVOMAINTENANCE_FW:=1}" = 1 && check_evomaintenance_fw test "${IS_REPVOLATILE:=1}" = 1 && check_repvolatile
test "${IS_MODDEFLATE:=1}" = 1 && check_moddeflate test "${IS_NETWORK_INTERFACES:=1}" = 1 && check_network_interfaces
test "${IS_LOG2MAILRUNNING:=1}" = 1 && check_log2mailrunning test "${IS_AUTOIF:=1}" = 1 && check_autoif
test "${IS_LOG2MAILAPACHE:=1}" = 1 && check_log2mailapache test "${IS_INTERFACESGW:=1}" = 1 && check_interfacesgw
test "${IS_LOG2MAILMYSQL:=1}" = 1 && check_log2mailmysql test "${IS_NETWORKING_SERVICE:=1}" = 1 && check_networking_service
test "${IS_LOG2MAILSQUID:=1}" = 1 && check_log2mailsquid test "${IS_EVOBACKUP:=1}" = 1 && check_evobackup
test "${IS_BINDCHROOT:=1}" = 1 && check_bindchroot test "${IS_EVOBACKUP_EXCLUDE_MOUNT:=1}" = 1 && check_evobackup_exclude_mount
test "${IS_REPVOLATILE:=1}" = 1 && check_repvolatile test "${IS_USERLOGROTATE:=1}" = 1 && check_userlogrotate
test "${IS_NETWORK_INTERFACES:=1}" = 1 && check_network_interfaces test "${IS_APACHECTL:=1}" = 1 && check_apachectl
test "${IS_AUTOIF:=1}" = 1 && check_autoif test "${IS_APACHESYMLINK:=1}" = 1 && check_apachesymlink
test "${IS_INTERFACESGW:=1}" = 1 && check_interfacesgw test "${IS_APACHEIPINALLOW:=1}" = 1 && check_apacheipinallow
test "${IS_NETWORKING_SERVICE:=1}" = 1 && check_networking_service test "${IS_MUNINAPACHECONF:=1}" = 1 && check_muninapacheconf
test "${IS_EVOBACKUP:=1}" = 1 && check_evobackup test "${IS_SAMBAPINPRIORITY:=1}" = 1 && check_sambainpriority
test "${IS_EVOBACKUP_EXCLUDE_MOUNT:=1}" = 1 && check_evobackup_exclude_mount test "${IS_KERNELUPTODATE:=1}" = 1 && check_kerneluptodate
test "${IS_USERLOGROTATE:=1}" = 1 && check_userlogrotate test "${IS_UPTIME:=1}" = 1 && check_uptime
test "${IS_APACHECTL:=1}" = 1 && check_apachectl test "${IS_MUNINRUNNING:=1}" = 1 && check_muninrunning
test "${IS_APACHESYMLINK:=1}" = 1 && check_apachesymlink test "${IS_BACKUPUPTODATE:=1}" = 1 && check_backupuptodate
test "${IS_APACHEIPINALLOW:=1}" = 1 && check_apacheipinallow test "${IS_ETCGIT:=1}" = 1 && check_etcgit
test "${IS_MUNINAPACHECONF:=1}" = 1 && check_muninapacheconf test "${IS_GITPERMS:=1}" = 1 && check_gitperms
test "${IS_SAMBAPINPRIORITY:=1}" = 1 && check_sambainpriority test "${IS_NOTUPGRADED:=1}" = 1 && check_notupgraded
test "${IS_KERNELUPTODATE:=1}" = 1 && check_kerneluptodate test "${IS_TUNE2FS_M5:=1}" = 1 && check_tune2fs_m5
test "${IS_UPTIME:=1}" = 1 && check_uptime test "${IS_EVOLINUXSUDOGROUP:=1}" = 1 && check_evolinuxsudogroup
test "${IS_MUNINRUNNING:=1}" = 1 && check_muninrunning test "${IS_USERINADMGROUP:=1}" = 1 && check_userinadmgroup
test "${IS_BACKUPUPTODATE:=1}" = 1 && check_backupuptodate test "${IS_APACHE2EVOLINUXCONF:=1}" = 1 && check_apache2evolinuxconf
test "${IS_ETCGIT:=1}" = 1 && check_etcgit test "${IS_BACKPORTSCONF:=1}" = 1 && check_backportsconf
test "${IS_GITPERMS:=1}" = 1 && check_gitperms test "${IS_BIND9MUNIN:=1}" = 1 && check_bind9munin
test "${IS_NOTUPGRADED:=1}" = 1 && check_notupgraded test "${IS_BIND9LOGROTATE:=1}" = 1 && check_bind9logrotate
test "${IS_TUNE2FS_M5:=1}" = 1 && check_tune2fs_m5 test "${IS_BROADCOMFIRMWARE:=1}" = 1 && check_broadcomfirmware
test "${IS_EVOLINUXSUDOGROUP:=1}" = 1 && check_evolinuxsudogroup test "${IS_HARDWARERAIDTOOL:=1}" = 1 && check_hardwareraidtool
test "${IS_USERINADMGROUP:=1}" = 1 && check_userinadmgroup test "${IS_LOG2MAILSYSTEMDUNIT:=1}" = 1 && check_log2mailsystemdunit
test "${IS_APACHE2EVOLINUXCONF:=1}" = 1 && check_apache2evolinuxconf test "${IS_LISTUPGRADE:=1}" = 1 && check_listupgrade
test "${IS_BACKPORTSCONF:=1}" = 1 && check_backportsconf test "${IS_MARIADBEVOLINUXCONF:=0}" = 1 && check_mariadbevolinuxconf
test "${IS_BIND9MUNIN:=1}" = 1 && check_bind9munin test "${IS_SQL_BACKUP:=1}" = 1 && check_sql_backup
test "${IS_BIND9LOGROTATE:=1}" = 1 && check_bind9logrotate test "${IS_POSTGRES_BACKUP:=1}" = 1 && check_postgres_backup
test "${IS_BROADCOMFIRMWARE:=1}" = 1 && check_broadcomfirmware test "${IS_MONGO_BACKUP:=1}" = 1 && check_mongo_backup
test "${IS_HARDWARERAIDTOOL:=1}" = 1 && check_hardwareraidtool test "${IS_LDAP_BACKUP:=1}" = 1 && check_ldap_backup
test "${IS_LOG2MAILSYSTEMDUNIT:=1}" = 1 && check_log2mailsystemdunit test "${IS_REDIS_BACKUP:=1}" = 1 && check_redis_backup
test "${IS_LISTUPGRADE:=1}" = 1 && check_listupgrade test "${IS_ELASTIC_BACKUP:=1}" = 1 && check_elastic_backup
test "${IS_MARIADBEVOLINUXCONF:=0}" = 1 && check_mariadbevolinuxconf test "${IS_MARIADBSYSTEMDUNIT:=1}" = 1 && check_mariadbsystemdunit
test "${IS_SQL_BACKUP:=1}" = 1 && check_sql_backup test "${IS_MYSQLMUNIN:=1}" = 1 && check_mysqlmunin
test "${IS_POSTGRES_BACKUP:=1}" = 1 && check_postgres_backup test "${IS_MYSQLNRPE:=1}" = 1 && check_mysqlnrpe
test "${IS_MONGO_BACKUP:=1}" = 1 && check_mongo_backup test "${IS_PHPEVOLINUXCONF:=0}" = 1 && check_phpevolinuxconf
test "${IS_LDAP_BACKUP:=1}" = 1 && check_ldap_backup test "${IS_SQUIDLOGROTATE:=1}" = 1 && check_squidlogrotate
test "${IS_REDIS_BACKUP:=1}" = 1 && check_redis_backup test "${IS_SQUIDEVOLINUXCONF:=1}" = 1 && check_squidevolinuxconf
test "${IS_ELASTIC_BACKUP:=1}" = 1 && check_elastic_backup test "${IS_DUPLICATE_FS_LABEL:=1}" = 1 && check_duplicate_fs_label
test "${IS_MARIADBSYSTEMDUNIT:=1}" = 1 && check_mariadbsystemdunit test "${IS_EVOLIX_USER:=1}" = 1 && check_evolix_user
test "${IS_MYSQLMUNIN:=1}" = 1 && check_mysqlmunin test "${IS_EVOACME_CRON:=1}" = 1 && check_evoacme_cron
test "${IS_MYSQLNRPE:=1}" = 1 && check_mysqlnrpe test "${IS_EVOACME_LIVELINKS:=1}" = 1 && check_evoacme_livelinks
test "${IS_PHPEVOLINUXCONF:=0}" = 1 && check_phpevolinuxconf test "${IS_APACHE_CONFENABLED:=1}" = 1 && check_apache_confenabled
test "${IS_SQUIDLOGROTATE:=1}" = 1 && check_squidlogrotate test "${IS_MELTDOWN_SPECTRE:=1}" = 1 && check_meltdown_spectre
test "${IS_SQUIDEVOLINUXCONF:=1}" = 1 && check_squidevolinuxconf test "${IS_OLD_HOME_DIR:=0}" = 1 && check_old_home_dir
test "${IS_DUPLICATE_FS_LABEL:=1}" = 1 && check_duplicate_fs_label test "${IS_EVOBACKUP_INCS:=1}" = 1 && check_evobackup_incs
test "${IS_EVOLIX_USER:=1}" = 1 && check_evolix_user test "${IS_OSPROBER:=1}" = 1 && check_osprober
test "${IS_EVOACME_CRON:=1}" = 1 && check_evoacme_cron test "${IS_JESSIE_BACKPORTS:=1}" = 1 && check_jessie_backports
test "${IS_EVOACME_LIVELINKS:=1}" = 1 && check_evoacme_livelinks test "${IS_APT_VALID_UNTIL:=1}" = 1 && check_apt_valid_until
test "${IS_APACHE_CONFENABLED:=1}" = 1 && check_apache_confenabled test "${IS_CHROOTED_BINARY_UPTODATE:=1}" = 1 && check_chrooted_binary_uptodate
test "${IS_MELTDOWN_SPECTRE:=1}" = 1 && check_meltdown_spectre test "${IS_NGINX_LETSENCRYPT_UPTODATE:=1}" = 1 && check_nginx_letsencrypt_uptodate
test "${IS_OLD_HOME_DIR:=0}" = 1 && check_old_home_dir test "${IS_LXC_CONTAINER_RESOLV_CONF:=1}" = 1 && check_lxc_container_resolv_conf
test "${IS_EVOBACKUP_INCS:=1}" = 1 && check_evobackup_incs test "${IS_CHECK_VERSIONS:=1}" = 1 && check_versions
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
fi
#-----------------------------------------------------------
# Tests spécifiques à OpenBSD
#-----------------------------------------------------------
if is_openbsd; then
if [ "${IS_SOFTDEP:=1}" = 1 ]; then
grep -q "softdep" /etc/fstab || failed "IS_SOFTDEP"
fi
if [ "${IS_WHEEL:=1}" = 1 ]; then
grep -qE "^%wheel.*$" /etc/sudoers || failed "IS_WHEEL"
fi
if [ "${IS_SUDOADMIN:=1}" = 1 ]; then
grep -qE "^User_Alias ADMIN=.*$" /etc/sudoers || failed "IS_SUDOADMIN"
fi
if [ "${IS_PKGMIRROR:=1}" = 1 ]; then
grep -qE "^export PKG_PATH=http://ftp\.fr\.openbsd\.org/pub/OpenBSD/[0-9.]+/packages/[a-z0-9]+/$" /root/.profile \
|| failed "IS_PKGMIRROR"
fi
if [ "${IS_HISTORY:=1}" = 1 ]; then
f=/root/.profile
{ grep -q "^HISTFILE=\$HOME/.histfile" $f \
&& grep -q "^export HISTFILE" $f \
&& grep -q "^HISTSIZE=1000" $f \
&& grep -q "^export HISTSIZE" $f;
} || failed "IS_HISTORY"
fi
if [ "${IS_VIM:=1}" = 1 ]; then
command -v vim > /dev/null 2>&1 || failed "IS_VIM"
fi
if [ "${IS_TTYC0SECURE:=1}" = 1 ]; then
grep -Eqv "^ttyC0.*secure$" /etc/ttys || failed "IS_TTYC0SECURE"
fi
if [ "${IS_CUSTOMSYSLOG:=1}" = 1 ]; then
grep -q "Evolix" /etc/newsyslog.conf || failed "IS_CUSTOMSYSLOG"
fi
if [ "${IS_NOINETD:=1}" = 1 ]; then
grep -q "inetd=NO" /etc/rc.conf.local 2>/dev/null || failed "IS_NOINETD"
fi
if [ "${IS_SUDOMAINT:=1}" = 1 ]; then
f=/etc/sudoers
{ grep -q "Cmnd_Alias MAINT = /usr/share/scripts/evomaintenance.sh" $f \
&& grep -q "ADMIN ALL=NOPASSWD: MAINT" $f;
} || failed "IS_SUDOMAINT"
fi
if [ "${IS_POSTGRESQL:=1}" = 1 ]; then
pkg info | grep -q postgresql-client || failed "IS_POSTGRESQL" "postgresql-client is not installed"
fi
if [ "${IS_NRPE:=1}" = 1 ]; then
{ pkg info | grep -qE "nagios-plugins-[0-9.]" \
&& pkg info | grep -q nagios-plugins-ntp \
&& pkg info | grep -q nrpe;
} || failed "IS_NRPE" "NRPE is not installed"
fi
# if [ "${IS_NRPEDISKS:=1}" = 1 ]; then
# NRPEDISKS=$(grep command.check_disk /etc/nrpe.cfg 2>/dev/null | grep "^command.check_disk[0-9]" | sed -e "s/^command.check_disk\([0-9]\+\).*/\1/" | sort -n | tail -1)
# DFDISKS=$(df -Pl | grep -E -v "(^Filesystem|/lib/init/rw|/dev/shm|udev|rpc_pipefs)" | wc -l)
# [ "$NRPEDISKS" = "$DFDISKS" ] || failed "IS_NRPEDISKS"
# fi
# Verification du check_mailq dans nrpe.cfg (celui-ci doit avoir l'option "-M postfix" si le MTA est Postfix)
#
# if [ "${IS_NRPEPOSTFIX:=1}" = 1 ]; then
# pkg info | grep -q postfix && ( grep -q "^command.*check_mailq -M postfix" /etc/nrpe.cfg 2>/dev/null || failed "IS_NRPEPOSTFIX" )
# fi
if [ "${IS_NRPEDAEMON:=1}" = 1 ]; then
grep -q "echo -n ' nrpe'; /usr/local/sbin/nrpe -d" /etc/rc.local \
|| failed "IS_NREPEDAEMON"
fi
if [ "${IS_ALERTBOOT:=1}" = 1 ]; then
grep -qE "^date \| mail -sboot/reboot .*evolix.fr$" /etc/rc.local \
|| failed "IS_ALERTBOOT"
fi
if [ "${IS_RSYNC:=1}" = 1 ]; then
pkg info | grep -q rsync || failed "IS_RSYNC"
fi
if [ "${IS_CRONPATH:=1}" = 1 ]; then
grep -q "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" /var/cron/tabs/root \
|| failed "IS_CRONPATH"
fi
#TODO
# - Check en profondeur de postfix
# - NRPEDISK et NRPEPOSTFIX
fi
if [ -f "${main_output_file}" ]; then if [ -f "${main_output_file}" ]; then
lines_found=$(wc -l < "${main_output_file}") lines_found=$(wc -l < "${main_output_file}")

View File

@ -1,12 +1,5 @@
--- ---
- name: Package install is not supported anymore
fail:
msg: Package install is not supported anymore
when:
- evocheck_force_install is defined
- evocheck_force_install == "package"
- include: install.yml - include: install.yml
- include: cron.yml - include: cron.yml

View File

@ -3,7 +3,7 @@
PROGNAME="update-evobackup-canary" PROGNAME="update-evobackup-canary"
REPOSITORY="https://gitea.evolix.org/evolix/evobackup" REPOSITORY="https://gitea.evolix.org/evolix/evobackup"
VERSION="22.05" VERSION="22.06"
readonly VERSION readonly VERSION
# base functions # base functions
@ -44,8 +44,8 @@ main() {
if [ -z "${canary_file:-}" ]; then if [ -z "${canary_file:-}" ]; then
canary_file="/zzz_evobackup_canary" canary_file="/zzz_evobackup_canary"
fi fi
# This option is supported since (at least) Debian 8 # This option is supported both on OpenBSD which does not use GNU date and on Debian
date=$(date --iso-8601=seconds) date=$(date "+%FT%T%z")
printf "%s %s\n" "${date}" "${who}" >> "${canary_file}" printf "%s %s\n" "${date}" "${who}" >> "${canary_file}"
} }

View File

@ -17,7 +17,7 @@
- name: update-evobackup-canary script is present - name: update-evobackup-canary script is present
copy: copy:
src: "update-evobackup-canary.sh" src: update-evobackup-canary
dest: /usr/local/bin/update-evobackup-canary dest: /usr/local/bin/update-evobackup-canary
force: True force: True
owner: root owner: root
@ -30,11 +30,11 @@
path: /usr/local/sbin/update-evobackup-canary path: /usr/local/sbin/update-evobackup-canary
state: absent state: absent
- name: dir-check script is present # - name: dir-check script is present
copy: # copy:
src: "dir-check.sh" # src: "dir-check.sh"
dest: /usr/local/bin/dir-check # dest: /usr/local/bin/dir-check
force: True # force: True
owner: root # owner: root
group: root # group: root
mode: "0755" # mode: "0755"

View File

@ -19,6 +19,7 @@ evolinux_users:
groups: "baz" groups: "baz"
password_hash: 'sdfgsdfgsdfgsdfg' password_hash: 'sdfgsdfgsdfgsdfg'
ssh_key: 'ssh-rsa AZERTYXYZ' ssh_key: 'ssh-rsa AZERTYXYZ'
create: always
bar: bar:
name: bar name: bar
uid: 1002 uid: 1002
@ -30,6 +31,7 @@ evolinux_users:
ssh_keys: ssh_keys:
- 'ssh-rsa QWERTYUIOP' - 'ssh-rsa QWERTYUIOP'
- 'ssh-ed25519 QWERTYUIOP' - 'ssh-ed25519 QWERTYUIOP'
create: on_demand
``` ```
* `evolinux_sudo_group`: which group to use for sudo (default: `evolinux-sudo`) * `evolinux_sudo_group`: which group to use for sudo (default: `evolinux-sudo`)

View File

@ -6,3 +6,6 @@ evolinux_ssh_group: "evolinux-ssh"
evolinux_internal_group: "" evolinux_internal_group: ""
evolinux_root_disable_ssh: True evolinux_root_disable_ssh: True
# Defines which groups of users are created
evolinux_users_create: always

View File

@ -16,7 +16,9 @@
vars: vars:
user: "{{ item.value }}" user: "{{ item.value }}"
loop: "{{ evolinux_users | dict2items }}" loop: "{{ evolinux_users | dict2items }}"
when: evolinux_users | length > 0 when:
- user.create == evolinux_users_create
- evolinux_users | length > 0
- name: Configure sudo - name: Configure sudo
include: sudo.yml include: sudo.yml

View File

@ -50,6 +50,7 @@
user: "{{ item.value }}" user: "{{ item.value }}"
loop: "{{ evolinux_users | dict2items }}" loop: "{{ evolinux_users | dict2items }}"
when: when:
- user.create == evolinux_users_create
- ssh_allowusers - ssh_allowusers
- not ssh_allowgroups - not ssh_allowgroups

View File

@ -6,6 +6,7 @@
loop: "{{ evolinux_users | dict2items }}" loop: "{{ evolinux_users | dict2items }}"
when: when:
- evolinux_users | length > 0 - evolinux_users | length > 0
- user.create == evolinux_users_create
- ansible_distribution_release == "jessie" - ansible_distribution_release == "jessie"
@ -16,6 +17,9 @@
vars: vars:
user: "{{ item.value }}" user: "{{ item.value }}"
loop: "{{ evolinux_users | dict2items }}" loop: "{{ evolinux_users | dict2items }}"
when:
- evolinux_users | length > 0
- user.create == evolinux_users_create
when: when:
- ansible_distribution_major_version is defined - ansible_distribution_major_version is defined
- ansible_distribution_major_version is version('9', '>=') - ansible_distribution_major_version is version('9', '>=')

View File

@ -1,3 +1,3 @@
[Definition] [Definition]
failregex = (?: pop3-login|imap-login): .*(?:Authentication failure|Aborted login \(auth failed|Aborted login \(tried to use disabled|Disconnected \(auth failed|Aborted login \(\d+ authentication attempts).*rip=(?P<host>\S*),.* failregex = (?: pop3-login|imap-login): .*(?:Authentication failure|Aborted login \(auth failed|Aborted login \(tried to use disabled|Disconnected \(auth failed|Aborted login \(\d+ authentication attempts).*rip=<HOST>,.*
ignoreregex = ignoreregex =

View File

@ -408,12 +408,8 @@ EOT
fi fi
# MariaDB # MariaDB
if is_pkg_installed mariadb-server-10.3; then if is_pkg_installed mariadb-server; then
mariadb_version=$(get_pkg_version mariadb-server-10.3) mariadb_version=$(get_pkg_version mariadb-server)
elif is_pkg_installed mariadb-server-10.1; then
mariadb_version=$(get_pkg_version mariadb-server-10.1)
elif is_pkg_installed mariadb-server-10.0; then
mariadb_version=$(get_pkg_version mariadb-server-10.0)
fi fi
if [ -n "${mariadb_version}" ]; then if [ -n "${mariadb_version}" ]; then
cat <<EOT >> "${ldif_file}" cat <<EOT >> "${ldif_file}"

View File

@ -1,4 +1,4 @@
[haproxy_*] [haproxy_*]
{% if haproxy_stats_internal_enable %} {% if haproxy_stats_internal_enable %}
env.url http://{{ haproxy_stats_internal_host }}:{{ haproxy_stats_internal_port }}/;csv;norefresh env.url http://{{ haproxy_stats_internal_host }}:{{ haproxy_stats_internal_port }}{{ haproxy_stats_path }};csv;norefresh
{% endif %} {% endif %}

View File

@ -3,7 +3,7 @@
- name: "{{ lxc_php_version }} - Install PHP packages" - name: "{{ lxc_php_version }} - Install PHP packages"
lxc_container: lxc_container:
name: "{{ lxc_php_version }}" name: "{{ lxc_php_version }}"
container_command: "DEBIAN_FRONTEND=noninteractive apt install -y php-fpm php-cli php-gd php-intl php-imap php-ldap php-mysql php-pgsql php-sqlite3 php-curl php-zip php-mbstring php-zip composer libphp-phpmailer" container_command: "DEBIAN_FRONTEND=noninteractive apt install -y php-fpm php-cli php-gd php-intl php-imap php-ldap php-mysql php-pgsql php-sqlite3 php-curl php-zip php-mbstring php-xml php-zip composer libphp-phpmailer"
- name: "{{ lxc_php_version }} - fix bullseye repository" - name: "{{ lxc_php_version }} - fix bullseye repository"
replace: replace:

View File

@ -46,7 +46,7 @@
- name: "{{ lxc_php_version }} - Install PHP packages" - name: "{{ lxc_php_version }} - Install PHP packages"
lxc_container: lxc_container:
name: "{{ lxc_php_version }}" name: "{{ lxc_php_version }}"
container_command: "DEBIAN_FRONTEND=noninteractive apt install -y php-fpm php-cli php-gd php-intl php-imap php-ldap php-mysql php-pgsql php-sqlite3 php-curl php-zip php-mbstring php-zip composer libphp-phpmailer" container_command: "DEBIAN_FRONTEND=noninteractive apt install -y php-fpm php-cli php-gd php-intl php-imap php-ldap php-mysql php-pgsql php-sqlite3 php-curl php-zip php-mbstring php-xml php-zip composer libphp-phpmailer"
- name: "{{ lxc_php_version }} - Copy evolinux PHP configuration" - name: "{{ lxc_php_version }} - Copy evolinux PHP configuration"
template: template:

View File

@ -46,7 +46,7 @@
- name: "{{ lxc_php_version }} - Install PHP packages" - name: "{{ lxc_php_version }} - Install PHP packages"
lxc_container: lxc_container:
name: "{{ lxc_php_version }}" name: "{{ lxc_php_version }}"
container_command: "DEBIAN_FRONTEND=noninteractive apt install -y php-fpm php-cli php-gd php-intl php-imap php-ldap php-mysql php-pgsql php-sqlite3 php-curl php-zip php-mbstring php-zip composer libphp-phpmailer" container_command: "DEBIAN_FRONTEND=noninteractive apt install -y php-fpm php-cli php-gd php-intl php-imap php-ldap php-mysql php-pgsql php-sqlite3 php-curl php-zip php-mbstring php-xml php-zip composer libphp-phpmailer"
- name: "{{ lxc_php_version }} - Copy evolinux PHP configuration" - name: "{{ lxc_php_version }} - Copy evolinux PHP configuration"
template: template:

View File

@ -0,0 +1,82 @@
#!/bin/bash
# {{ ansible_managed }}
set -u
return=0
nb_crit=0
nb_warn=0
nb_ok=0
nb_unchk=0
output=""
vendored_check=/usr/local/lib/nagios/plugins/check_memcached.pl
if [ -x $vendored_check ]; then
check_bin=$vendored_check
else
echo "UNCHK - can't find check_memcached"
exit 3
fi
check_server() {
name=$1
conf_file=$2
host=$(config_var "-l" "${conf_file}")
port=$(config_var "-p" "${conf_file}")
cmd="${check_bin} -H ${host} -p ${port}"
result=$($cmd)
ret="${?}"
if [ "${ret}" -ge 2 ]; then
nb_crit=$((nb_crit + 1))
printf -v output "%s%s\n" "${output}" "${result}"
[ "${return}" -le 2 ] && return=2
elif [ "${ret}" -ge 1 ]; then
nb_warn=$((nb_warn + 1))
printf -v output "%s%s\n" "${output}" "${result}"
[ "${return}" -le 1 ] && return=1
else
nb_ok=$((nb_ok + 1))
printf -v output "%s%s\n" "${output}" "${result}"
[ "${return}" -le 0 ] && return=0
fi
}
config_var() {
variable=$1
file=$2
test -f "${file}" && grep -E "^${variable}\s+.+$" "${file}" | awk '{ print $2 }' | sed -e "s/^[\"']//" -e "s/[\"']$//"
}
# default instance
if systemctl is-enabled -q memcached; then
check_server "default" "/etc/memcached.conf"
fi
# additional instances
conf_files=$(ls -1 /etc/memcached_*.conf 2> /dev/null)
for conf_file in ${conf_files}; do
name=$(basename "${conf_file}" | sed '{s|memcached_||;s|\.conf||}')
if systemctl is-enabled -q "memcached@${name}.service"; then
check_server "${name}" "${conf_file}"
else
nb_unchk=$((nb_unchk + 1))
output="${output}UNCHK - ${name} (unit is disabled or missing)\n"
fi
done
[ "${return}" -ge 0 ] && header="OK"
[ "${return}" -ge 1 ] && header="WARNING"
[ "${return}" -ge 2 ] && header="CRITICAL"
printf "%s - %s UNCHK / %s CRIT / %s WARN / %s OK\n\n" "${header}" "${nb_unchk}" "${nb_crit}" "${nb_warn}" "${nb_ok}"
printf "%s" "${output}" | grep -E "CRITICAL"
printf "%s" "${output}" | grep -E "WARNING"
printf "%s" "${output}" | grep -E "OK"
printf "%s" "${output}" | grep -E "UNCHK"
exit "${return}"

View File

@ -0,0 +1,17 @@
- name: Memcached is configured.
template:
src: memcached.conf.j2
dest: /etc/memcached.conf
mode: "0644"
notify: restart memcached
tags:
- memcached
- name: Memcached is running and enabled on boot.
service:
name: memcached
enabled: yes
state: started
tags:
- memcached

View File

@ -0,0 +1,41 @@
---
- name: Add systemd unit template
copy:
src: memcached@.service
dest: /etc/systemd/system/memcached@.service
tags:
- memcached
- name: Disable default memcached systemd unit
systemd:
name: memcached
enabled: false
state: stopped
tags:
- memcached
- name: Make sure memcached.conf is absent
file:
path: /etc/memcached.conf
state: absent
tags:
- memcached
- name: "Create a configuration file for instance ({{ memcached_instance_name }})"
template:
src: memcached.conf.j2
dest: /etc/memcached_{{ memcached_instance_name }}.conf
mode: "0644"
tags:
- memcached
- name: "Enable and start the memcached instance ({{ memcached_instance_name }})"
systemd:
name: memcached@{{ memcached_instance_name }}
enabled: yes
state: started
daemon_reload: yes
masked: no
tags:
- memcached

View File

@ -1,73 +1,15 @@
- name: ensure packages are installed - name: Ensure memcached is installed
apt: apt:
name: memcached name: memcached
state: present state: present
tags: tags:
- memcached - memcached
- name: Memcached is configured. - include: instance-default.yml
template: when: memcached_instance_name is undefined
src: memcached.conf.j2
dest: /etc/memcached.conf
mode: "0644"
notify: restart memcached
tags:
- memcached
when: memcached_instance_name | length == 0
- name: Memcached is running and enabled on boot. - include: instance-multi.yml
service: when: memcached_instance_name is defined
name: memcached
enabled: yes
state: started
tags:
- memcached
when: memcached_instance_name | length == 0
- name: Add systemd template
copy:
src: memcached@.service
dest: /etc/systemd/system/memcached@.service
tags:
- memcached
when: memcached_instance_name | length > 0
- name: Delete default memcached systemd configuration file
systemd:
name: memcached
enabled: false
state: stopped
tags:
- memcached
when: memcached_instance_name | length > 0
- name: Make sure memcached.conf is absent
file:
path: /etc/memcached.conf
state: absent
tags:
- memcached
when: memcached_instance_name | length > 0
- name: Create a configuration file
template:
src: memcached.conf.j2
dest: /etc/memcached_{{ memcached_instance_name }}.conf
mode: "0644"
tags:
- memcached
when: memcached_instance_name | length > 0
- name: Enable and start the memcached instance
systemd:
name: memcached@{{ memcached_instance_name }}
enabled: yes
state: started
daemon_reload: yes
masked: no
tags:
- memcached
when: memcached_instance_name | length > 0
- include: munin.yml - include: munin.yml

View File

@ -2,7 +2,7 @@
- name: Choose packages (Oracle) - name: Choose packages (Oracle)
set_fact: set_fact:
multi: "multi_" multi: "multi_"
when: memcached_instance_name | length > 0 when: memcached_instance_name is defined
- name: is Munin present ? - name: is Munin present ?
stat: stat:

View File

@ -1,6 +1,4 @@
--- ---
- include_role:
name: evolix/remount-usr
- name: Is nrpe present ? - name: Is nrpe present ?
stat: stat:
@ -10,7 +8,12 @@
- block: - block:
- name: Install dependencies - name: Install dependencies
apt: apt:
name: libcache-memcached-perl name:
- libcache-memcached-perl
- libmemcached11
- include_role:
name: evolix/remount-usr
- name: Copy Nagios check for memcached - name: Copy Nagios check for memcached
copy: copy:
@ -18,13 +21,29 @@
dest: /usr/local/lib/nagios/plugins/ dest: /usr/local/lib/nagios/plugins/
mode: "0755" mode: "0755"
# TODO: install a "multi-instances" check if the memcached_instance_name variable is not null - name: install check_memcached_instances
copy:
src: check_memcached_instances.sh
dest: /usr/local/lib/nagios/plugins/check_memcached_instances
force: yes
mode: "0755"
owner: root
group: root
- name: Add NRPE check - name: Add NRPE check (single instance)
lineinfile: lineinfile:
name: /etc/nagios/nrpe.d/evolix.cfg name: /etc/nagios/nrpe.d/evolix.cfg
regexp: '^command\[check_memcached\]=' regexp: '^command\[check_memcached\]='
line: 'command[check_memcached]=/usr/local/lib/nagios/plugins/check_memcached.pl -H 127.0.0.1 -p {{ memcached_port }}' line: 'command[check_memcached]=/usr/local/lib/nagios/plugins/check_memcached.pl -H 127.0.0.1 -p {{ memcached_port }}'
notify: restart nagios-nrpe-server notify: restart nagios-nrpe-server
when: memcached_instance_name is undefined
- name: Add NRPE check (multi instance)
lineinfile:
name: /etc/nagios/nrpe.d/evolix.cfg
regexp: '^command\[check_memcached\]='
line: 'command[check_memcached]=/usr/local/lib/nagios/plugins/check_memcached_instances'
notify: restart nagios-nrpe-server
when: memcached_instance_name is defined
when: nrpe_evolix_config.stat.exists when: nrpe_evolix_config.stat.exists

View File

@ -4,3 +4,19 @@
service: service:
name: nagios-nrpe-server name: nagios-nrpe-server
state: restarted state: restarted
- name: restart minifirewall (modern)
command: /etc/init.d/minifirewall restart
register: minifirewall_init_restart
failed_when: "'minifirewall failed' in minifirewall_init_restart.stdout"
- name: restart minifirewall (legacy)
command: /etc/init.d/minifirewall restart
register: minifirewall_init_restart
failed_when: "'starting IPTables rules is now finish : OK' not in minifirewall_init_restart.stdout"
- name: restart minifirewall (noop)
meta: noop
register: minifirewall_init_restart
failed_when: False
changed_when: False

View File

@ -197,21 +197,15 @@
path: "{{ minifirewall_main_file }}" path: "{{ minifirewall_main_file }}"
register: minifirewall_after register: minifirewall_after
- name: restart minifirewall - name: Schedule minifirewall restart (legacy)
command: /etc/init.d/minifirewall restart command: /bin/true
register: minifirewall_init_restart notify: "restart minifirewall (legacy)"
failed_when: "'starting IPTables rules is now finish : OK' not in minifirewall_init_restart.stdout"
when: when:
- minifirewall_install_mode == 'legacy'
- minifirewall_restart_if_needed | bool - minifirewall_restart_if_needed | bool
- minifirewall_is_running.rc == 0 - minifirewall_is_running.rc == 0
- minifirewall_before.stat.checksum != minifirewall_after.stat.checksum - minifirewall_before.stat.checksum != minifirewall_after.stat.checksum or minifirewall_upgrade_script is changed or minifirewall_upgrade_config is changed
- name: restart minifirewall (noop)
meta: noop
register: minifirewall_init_restart
failed_when: False
changed_when: False
when: not (minifirewall_restart_if_needed | bool)
- debug: - debug:
var: minifirewall_init_restart var: minifirewall_init_restart

View File

@ -282,11 +282,11 @@
path: "/etc/default/minifirewall" path: "/etc/default/minifirewall"
register: minifirewall_after register: minifirewall_after
- name: restart minifirewall - name: Schedule minifirewall restart (modern)
command: /etc/init.d/minifirewall restart command: /bin/true
register: minifirewall_init_restart notify: "restart minifirewall (modern)"
failed_when: "'minifirewall failed' in minifirewall_init_restart.stdout"
when: when:
- minifirewall_install_mode != 'legacy'
- minifirewall_restart_if_needed | bool - minifirewall_restart_if_needed | bool
- minifirewall_is_running.rc == 0 - minifirewall_is_running.rc == 0
- minifirewall_before.stat.checksum != minifirewall_after.stat.checksum or minifirewall_upgrade_script is changed or minifirewall_upgrade_config is changed - minifirewall_before.stat.checksum != minifirewall_after.stat.checksum or minifirewall_upgrade_script is changed or minifirewall_upgrade_config is changed

View File

@ -1,9 +1,5 @@
--- ---
- name: Compose minifirewall_restart_handler_name variable
set_fact:
minifirewall_restart_handler_name: "{{ minifirewall_restart_if_needed | bool | ternary('restart minifirewall', 'restart minifirewall (noop)') }}"
# Legacy or modern mode? ############################################## # Legacy or modern mode? ##############################################
- name: Check minifirewall - name: Check minifirewall
@ -39,6 +35,25 @@
var: minifirewall_install_mode var: minifirewall_install_mode
verbosity: 1 verbosity: 1
- name: 'Set minifirewall_restart_handler_name to "noop"'
set_fact:
minifirewall_restart_handler_name: "restart minifirewall (noop)"
when: not (minifirewall_restart_if_needed | bool)
- name: 'Set minifirewall_restart_handler_name to "legacy"'
set_fact:
minifirewall_restart_handler_name: "restart minifirewall (legacy)"
when:
- minifirewall_restart_if_needed | bool
- minifirewall_install_mode == 'legacy'
- name: 'Set minifirewall_restart_handler_name to "modern"'
set_fact:
minifirewall_restart_handler_name: "restart minifirewall (modern)"
when:
- minifirewall_restart_if_needed | bool
- minifirewall_install_mode != 'legacy'
####################################################################### #######################################################################
- name: Fail if minifirewall_main_file is defined (legacy mode) - name: Fail if minifirewall_main_file is defined (legacy mode)
@ -106,18 +121,16 @@
var: minifirewall_restart_force | bool var: minifirewall_restart_force | bool
verbosity: 1 verbosity: 1
- name: Force restart minifirewall (modern mode) - name: Force restart minifirewall (legacy)
command: /etc/init.d/minifirewall restart command: /bin/true
register: minifirewall_init_restart notify: "restart minifirewall (legacy)"
failed_when: "'minifirewall failed' in minifirewall_init_restart.stdout"
when:
- minifirewall_install_mode != 'legacy'
- minifirewall_restart_force | bool
- name: Force restart minifirewall (legacy mode)
command: /etc/init.d/minifirewall restart
register: minifirewall_init_restart
failed_when: "'starting IPTables rules is now finish : OK' not in minifirewall_init_restart.stdout"
when: when:
- minifirewall_install_mode == 'legacy' - minifirewall_install_mode == 'legacy'
- minifirewall_restart_force | bool
- name: Force restart minifirewall (modern)
command: /bin/true
notify: "restart minifirewall (modern)"
when:
- minifirewall_install_mode != 'legacy'
- minifirewall_restart_force | bool - minifirewall_restart_force | bool

View File

@ -1,4 +1,22 @@
--- ---
- name: Stat minifirewall config file (before)
stat:
path: "/etc/default/minifirewall"
register: minifirewall_before
- name: Check if minifirewall is running
shell:
cmd: /sbin/iptables -L -n | grep -E "^(DROP\s+udp|ACCEPT\s+icmp)\s+--\s+0\.0\.0\.0\/0\s+0\.0\.0\.0\/0\s*$"
changed_when: False
failed_when: False
check_mode: no
register: minifirewall_is_running
- debug:
var: minifirewall_is_running
verbosity: 1
- name: Add some rules at the end of minifirewall file - name: Add some rules at the end of minifirewall file
template: template:
src: "{{ item }}" src: "{{ item }}"
@ -30,20 +48,14 @@
var: minifirewall_tail_source var: minifirewall_tail_source
verbosity: 1 verbosity: 1
- name: restart minifirewall - name: Schedule minifirewall restart (legacy)
command: /etc/init.d/minifirewall restart command: /bin/true
register: minifirewall_init_restart notify: "restart minifirewall (legacy)"
failed_when: "'starting IPTables rules is now finish : OK' not in minifirewall_init_restart.stdout"
when: when:
- minifirewall_tail_template is changed - minifirewall_install_mode == 'legacy'
- minifirewall_restart_if_needed | bool - minifirewall_restart_if_needed | bool
- minifirewall_is_running.rc == 0
- name: restart minifirewall (noop) - minifirewall_tail_template is changed
meta: noop
register: minifirewall_init_restart
failed_when: False
changed_when: False
when: not (minifirewall_restart_if_needed | bool)
- debug: - debug:
var: minifirewall_init_restart var: minifirewall_init_restart

View File

@ -1,4 +1,22 @@
--- ---
- name: Stat minifirewall config file (before)
stat:
path: "/etc/default/minifirewall"
register: minifirewall_before
- name: Check if minifirewall is running
shell:
cmd: /sbin/iptables -L -n | grep -E "^(DROP\s+udp|ACCEPT\s+icmp)\s+--\s+0\.0\.0\.0\/0\s+0\.0\.0\.0\/0\s*$"
changed_when: False
failed_when: False
check_mode: no
register: minifirewall_is_running
- debug:
var: minifirewall_is_running
verbosity: 1
- name: Add some rules at the end of minifirewall file - name: Add some rules at the end of minifirewall file
template: template:
src: "{{ item }}" src: "{{ item }}"
@ -18,20 +36,14 @@
var: minifirewall_tail_template var: minifirewall_tail_template
verbosity: 1 verbosity: 1
- name: restart minifirewall - name: Schedule minifirewall restart (modern)
command: /etc/init.d/minifirewall restart command: /bin/true
register: minifirewall_init_restart notify: "restart minifirewall (modern)"
failed_when: "'minifirewall failed' in minifirewall_init_restart.stdout"
when: when:
- minifirewall_tail_template is changed - minifirewall_install_mode != 'legacy'
- minifirewall_restart_if_needed | bool - minifirewall_restart_if_needed | bool
- minifirewall_is_running.rc == 0
- name: restart minifirewall (noop) - minifirewall_tail_template is changed
meta: noop
register: minifirewall_init_restart
failed_when: False
changed_when: False
when: not (minifirewall_restart_if_needed | bool)
- debug: - debug:
var: minifirewall_init_restart var: minifirewall_init_restart

View File

@ -1,12 +1,13 @@
--- ---
- name: Ensure that Munin is installed - name: Ensure that Munin (and useful dependencies) is installed
apt: apt:
name: name:
- munin - munin
- munin-node - munin-node
- munin-plugins-core - munin-plugins-core
- munin-plugins-extra - munin-plugins-extra
- gawk
state: present state: present
tags: tags:
- munin - munin
@ -79,16 +80,32 @@
tags: tags:
- munin - munin
- name: Enable sensors plugin unless VM detected - name: Enable sensors_ plugin on dedicated hardware
file: file:
src: /usr/share/munin/plugins/sensors_ src: /usr/share/munin/plugins/sensors_
dest: /etc/munin/plugins/sensors_temp dest: "/etc/munin/plugins/sensors_{{ item }}"
state: link state: link
when: ansible_virtualization_role != "guest" with_items:
- fan
- temp
when: ansible_virtualization_role == "host"
notify: restart munin-node notify: restart munin-node
tags: tags:
- munin - munin
- name: Enable ipmi_ plugin on dedicated hardware
file:
src: /usr/share/munin/plugins/ipmi_
dest: "/etc/munin/plugins/ipmi_{{ item }}"
state: link
when: ansible_virtualization_role == "host"
notify: restart munin-node
with_items:
- fans
- temp
- power
- volts
- name: adjustments for grsec kernel - name: adjustments for grsec kernel
blockinfile: blockinfile:
dest: /etc/munin/plugin-conf.d/munin-node dest: /etc/munin/plugin-conf.d/munin-node

View File

@ -66,13 +66,42 @@
- replication - replication
notify: restart munin-node notify: restart munin-node
- name: verify Munin configuration for mysql - name: verify Munin configuration for mysql < Debian 11
replace: replace:
dest: /etc/munin/plugin-conf.d/munin-node dest: /etc/munin/plugin-conf.d/munin-node
after: '\[mysql\*\]' after: '\[mysql\*\]'
regexp: '^env.mysqluser (.+)$' regexp: '^env.mysqluser (.+)$'
replace: 'env.mysqluser debian-sys-maint' replace: 'env.mysqluser debian-sys-maint'
notify: restart munin-node notify: restart munin-node
when: ansible_distribution_major_version is version_compare('11', '<')
- name: set Munin env.mysqluser option for mysql >= Debian 11
replace:
dest: /etc/munin/plugin-conf.d/munin-node
after: '\[mysql\*\]'
regexp: '^env.mysqluser (.+)$'
replace: 'env.mysqluser root'
notify: restart munin-node
when: ansible_distribution_major_version is version_compare('11', '>=')
- name: set Munin env.mysqlopts option for mysql >= Debian 11
replace:
dest: /etc/munin/plugin-conf.d/munin-node
after: '\[mysql\*\]'
regexp: '^env.mysqlopts (.+)$'
replace: 'env.mysqlopts --defaults-file=/root/.my.cnf'
notify: restart munin-node
when: ansible_distribution_major_version is version_compare('11', '>=')
- name: set Munin env.mysqlconnection option for mysql >= Debian 11
replace:
dest: /etc/munin/plugin-conf.d/munin-node
after: '\[mysql\*\]'
regexp: '^env.mysqlconnection (.+)$'
replace: 'env.mysqlconnection DBI:mysql:mysql;mysql_read_default_file=/root/.my.cnf'
notify: restart munin-node
when: ansible_distribution_major_version is version_compare('11', '>=')
when: munin_node_plugins_config.stat.exists when: munin_node_plugins_config.stat.exists
tags: tags:

653
nagios-nrpe/files/plugins/check_mongodb Executable file → Normal file
View File

@ -17,24 +17,29 @@
# - Dag Stockstad <dag.stockstad@gmail.com> # - Dag Stockstad <dag.stockstad@gmail.com>
# - @Andor on github # - @Andor on github
# - Steven Richards - Captainkrtek on github # - Steven Richards - Captainkrtek on github
# - Max Vernimmen # - Max Vernimmen - @mvernimmen-CG / @mvernimmen on github
# - Kris Nova - @kris@nivenly.com github.com/kris-nova
# - Jan Kantert - firstname@lastname.net
# #
# USAGE # USAGE
# #
# See the README.md # See the README.md
# #
from __future__ import print_function
from __future__ import division
import sys import sys
import time import time
import optparse import optparse
import textwrap
import re import re
import os import os
import numbers
import socket
try: try:
import pymongo import pymongo
except ImportError, e: except ImportError as e:
print e print(e)
sys.exit(2) sys.exit(2)
# As of pymongo v 1.9 the SON API is part of the BSON package, therefore attempt # As of pymongo v 1.9 the SON API is part of the BSON package, therefore attempt
@ -78,37 +83,35 @@ def performance_data(perf_data, params):
def numeric_type(param): def numeric_type(param):
if ((type(param) == float or type(param) == int or param == None)): return param is None or isinstance(param, numbers.Real)
return True
return False
def check_levels(param, warning, critical, message, ok=[]): def check_levels(param, warning, critical, message, ok=[]):
if (numeric_type(critical) and numeric_type(warning)): if (numeric_type(critical) and numeric_type(warning)):
if param >= critical: if param >= critical:
print "CRITICAL - " + message print("CRITICAL - " + message)
sys.exit(2) sys.exit(2)
elif param >= warning: elif param >= warning:
print "WARNING - " + message print("WARNING - " + message)
sys.exit(1) sys.exit(1)
else: else:
print "OK - " + message print("OK - " + message)
sys.exit(0) sys.exit(0)
else: else:
if param in critical: if param in critical:
print "CRITICAL - " + message print("CRITICAL - " + message)
sys.exit(2) sys.exit(2)
if param in warning: if param in warning:
print "WARNING - " + message print("WARNING - " + message)
sys.exit(1) sys.exit(1)
if param in ok: if param in ok:
print "OK - " + message print("OK - " + message)
sys.exit(0) sys.exit(0)
# unexpected param value # unexpected param value
print "CRITICAL - Unexpected value : %d" % param + "; " + message print("CRITICAL - Unexpected value : %d" % param + "; " + message)
return 2 return 2
@ -120,21 +123,32 @@ def get_server_status(con):
data = con.admin.command(son.SON([('serverStatus', 1)])) data = con.admin.command(son.SON([('serverStatus', 1)]))
return data return data
def split_host_port(string):
if not string.rsplit(':', 1)[-1].isdigit():
return (string, None)
string = string.rsplit(':', 1)
host = string[0] # 1st index is always host
port = int(string[1])
return (host, port)
def main(argv): def main(argv):
p = optparse.OptionParser(conflict_handler="resolve", description="This Nagios plugin checks the health of mongodb.") p = optparse.OptionParser(conflict_handler="resolve", description="This Nagios plugin checks the health of mongodb.")
p.add_option('-H', '--host', action='store', type='string', dest='host', default='127.0.0.1', help='The hostname you want to connect to') p.add_option('-H', '--host', action='store', type='string', dest='host', default='127.0.0.1', help='The hostname you want to connect to')
p.add_option('-P', '--port', action='store', type='int', dest='port', default=27017, help='The port mongodb is runnung on') p.add_option('-h', '--host-to-check', action='store', type='string', dest='host_to_check', default=None, help='The hostname you want to check (if this is different from the host you are connecting)')
p.add_option('--rdns-lookup', action='store_true', dest='rdns_lookup', default=False, help='RDNS(PTR) lookup on given host/host-to-check, to convert ip-address to fqdn')
p.add_option('-P', '--port', action='store', type='int', dest='port', default=27017, help='The port mongodb is running on')
p.add_option('--port-to-check', action='store', type='int', dest='port_to_check', default=None, help='The port you want to check (if this is different from the port you are connecting)')
p.add_option('-u', '--user', action='store', type='string', dest='user', default=None, help='The username you want to login as') p.add_option('-u', '--user', action='store', type='string', dest='user', default=None, help='The username you want to login as')
p.add_option('-p', '--pass', action='store', type='string', dest='passwd', default=None, help='The password you want to use for that user') p.add_option('-p', '--pass', action='store', type='string', dest='passwd', default=None, help='The password you want to use for that user')
p.add_option('-W', '--warning', action='store', dest='warning', default=None, help='The warning threshold we want to set') p.add_option('-W', '--warning', action='store', dest='warning', default=None, help='The warning threshold you want to set')
p.add_option('-C', '--critical', action='store', dest='critical', default=None, help='The critical threshold we want to set') p.add_option('-C', '--critical', action='store', dest='critical', default=None, help='The critical threshold you want to set')
p.add_option('-A', '--action', action='store', type='choice', dest='action', default='connect', help='The action you want to take', p.add_option('-A', '--action', action='store', type='choice', dest='action', default='connect', help='The action you want to take',
choices=['connect', 'connections', 'replication_lag', 'replication_lag_percent', 'replset_state', 'memory', 'memory_mapped', 'lock', choices=['connect', 'connections', 'replication_lag', 'replication_lag_percent', 'replset_state', 'memory', 'memory_mapped', 'lock',
'flushing', 'last_flush_time', 'index_miss_ratio', 'databases', 'collections', 'database_size', 'database_indexes', 'collection_indexes', 'collection_size', 'flushing', 'last_flush_time', 'index_miss_ratio', 'databases', 'collections', 'database_size', 'database_indexes', 'collection_documents', 'collection_indexes', 'collection_size',
'queues', 'oplog', 'journal_commits_in_wl', 'write_data_files', 'journaled', 'opcounters', 'current_lock', 'replica_primary', 'page_faults', 'collection_storageSize', 'queues', 'oplog', 'journal_commits_in_wl', 'write_data_files', 'journaled', 'opcounters', 'current_lock', 'replica_primary',
'asserts', 'queries_per_second', 'page_faults', 'chunks_balance', 'connect_primary', 'collection_state', 'row_count', 'replset_quorum']) 'page_faults', 'asserts', 'queries_per_second', 'page_faults', 'chunks_balance', 'connect_primary', 'collection_state', 'row_count', 'replset_quorum'])
p.add_option('--max-lag', action='store_true', dest='max_lag', default=False, help='Get max replication lag (for replication_lag action only)') p.add_option('--max-lag', action='store_true', dest='max_lag', default=False, help='Get max replication lag (for replication_lag action only)')
p.add_option('--mapped-memory', action='store_true', dest='mapped_memory', default=False, help='Get mapped memory instead of resident (if resident memory can not be read)') p.add_option('--mapped-memory', action='store_true', dest='mapped_memory', default=False, help='Get mapped memory instead of resident (if resident memory can not be read)')
p.add_option('-D', '--perf-data', action='store_true', dest='perf_data', default=False, help='Enable output of Nagios performance data') p.add_option('-D', '--perf-data', action='store_true', dest='perf_data', default=False, help='Enable output of Nagios performance data')
@ -145,12 +159,28 @@ def main(argv):
p.add_option('-q', '--querytype', action='store', dest='query_type', default='query', help='The query type to check [query|insert|update|delete|getmore|command] from queries_per_second') p.add_option('-q', '--querytype', action='store', dest='query_type', default='query', help='The query type to check [query|insert|update|delete|getmore|command] from queries_per_second')
p.add_option('-c', '--collection', action='store', dest='collection', default='admin', help='Specify the collection to check') p.add_option('-c', '--collection', action='store', dest='collection', default='admin', help='Specify the collection to check')
p.add_option('-T', '--time', action='store', type='int', dest='sample_time', default=1, help='Time used to sample number of pages faults') p.add_option('-T', '--time', action='store', type='int', dest='sample_time', default=1, help='Time used to sample number of pages faults')
p.add_option('-M', '--mongoversion', action='store', type='choice', dest='mongo_version', default='2', help='The MongoDB version you are talking with, either 2 or 3',
choices=['2','3'])
p.add_option('-a', '--authdb', action='store', type='string', dest='authdb', default='admin', help='The database you want to authenticate against')
p.add_option('--insecure', action='store_true', dest='insecure', default=False, help="Don't verify SSL/TLS certificates")
p.add_option('--ssl-ca-cert-file', action='store', type='string', dest='ssl_ca_cert_file', default=None, help='Path to Certificate Authority file for SSL')
p.add_option('-f', '--ssl-cert-file', action='store', type='string', dest='cert_file', default=None, help='Path to PEM encoded key and cert for client authentication')
p.add_option('-m','--auth-mechanism', action='store', type='choice', dest='auth_mechanism', default=None, help='Auth mechanism used for auth with mongodb',
choices=['MONGODB-X509','SCRAM-SHA-256','SCRAM-SHA-1'])
p.add_option('--disable_retry_writes', dest='retry_writes_disabled', default=False, action='callback', callback=optional_arg(True), help='Disable retryWrites feature')
options, arguments = p.parse_args() options, arguments = p.parse_args()
host = options.host host = options.host
host_to_check = options.host_to_check if options.host_to_check else options.host
rdns_lookup = options.rdns_lookup
if (rdns_lookup):
host_to_check = socket.getnameinfo((host_to_check, 0), 0)[0]
port = options.port port = options.port
port_to_check = options.port_to_check if options.port_to_check else options.port
user = options.user user = options.user
passwd = options.passwd passwd = options.passwd
authdb = options.authdb
query_type = options.query_type query_type = options.query_type
collection = options.collection collection = options.collection
sample_time = options.sample_time sample_time = options.sample_time
@ -164,9 +194,15 @@ def main(argv):
action = options.action action = options.action
perf_data = options.perf_data perf_data = options.perf_data
max_lag = options.max_lag max_lag = options.max_lag
mongo_version = options.mongo_version
database = options.database database = options.database
ssl = options.ssl ssl = options.ssl
replicaset = options.replicaset replicaset = options.replicaset
insecure = options.insecure
ssl_ca_cert_file = options.ssl_ca_cert_file
cert_file = options.cert_file
auth_mechanism = options.auth_mechanism
retry_writes_disabled = options.retry_writes_disabled
if action == 'replica_primary' and replicaset is None: if action == 'replica_primary' and replicaset is None:
return "replicaset must be passed in when using replica_primary check" return "replicaset must be passed in when using replica_primary check"
@ -177,31 +213,35 @@ def main(argv):
# moving the login up here and passing in the connection # moving the login up here and passing in the connection
# #
start = time.time() start = time.time()
err, con = mongo_connect(host, port, ssl, user, passwd, replicaset) err, con = mongo_connect(host, port, ssl, user, passwd, replicaset, authdb, insecure, ssl_ca_cert_file, cert_file, auth_mechanism, retry_writes_disabled=retry_writes_disabled)
if err != 0:
return err
# Autodetect mongo-version and force pymongo to let us know if it can connect or not.
err, mongo_version = check_version(con)
if err != 0: if err != 0:
return err return err
conn_time = time.time() - start conn_time = time.time() - start
conn_time = round(conn_time, 0)
if action == "connections": if action == "connections":
return check_connections(con, warning, critical, perf_data) return check_connections(con, warning, critical, perf_data)
elif action == "replication_lag": elif action == "replication_lag":
return check_rep_lag(con, host, port, warning, critical, False, perf_data, max_lag, user, passwd) return check_rep_lag(con, host_to_check, port_to_check, rdns_lookup, warning, critical, False, perf_data, max_lag, ssl, user, passwd, replicaset, authdb, insecure, ssl_ca_cert_file, cert_file, auth_mechanism, retry_writes_disabled=retry_writes_disabled)
elif action == "replication_lag_percent": elif action == "replication_lag_percent":
return check_rep_lag(con, host, port, warning, critical, True, perf_data, max_lag, user, passwd) return check_rep_lag(con, host_to_check, port_to_check, rdns_lookup, warning, critical, True, perf_data, max_lag, ssl, user, passwd, replicaset, authdb, insecure, ssl_ca_cert_file, cert_file, auth_mechanism, retry_writes_disabled=retry_writes_disabled)
elif action == "replset_state": elif action == "replset_state":
return check_replset_state(con, perf_data, warning, critical) return check_replset_state(con, perf_data, warning, critical)
elif action == "memory": elif action == "memory":
return check_memory(con, warning, critical, perf_data, options.mapped_memory) return check_memory(con, warning, critical, perf_data, options.mapped_memory, host)
elif action == "memory_mapped": elif action == "memory_mapped":
return check_memory_mapped(con, warning, critical, perf_data) return check_memory_mapped(con, warning, critical, perf_data)
elif action == "queues": elif action == "queues":
return check_queues(con, warning, critical, perf_data) return check_queues(con, warning, critical, perf_data)
elif action == "lock": elif action == "lock":
return check_lock(con, warning, critical, perf_data) return check_lock(con, warning, critical, perf_data, mongo_version)
elif action == "current_lock": elif action == "current_lock":
return check_current_lock(con, host, warning, critical, perf_data) return check_current_lock(con, host, port, warning, critical, perf_data)
elif action == "flushing": elif action == "flushing":
return check_flushing(con, warning, critical, True, perf_data) return check_flushing(con, warning, critical, True, perf_data)
elif action == "last_flush_time": elif action == "last_flush_time":
@ -223,22 +263,26 @@ def main(argv):
return check_database_size(con, database, warning, critical, perf_data) return check_database_size(con, database, warning, critical, perf_data)
elif action == "database_indexes": elif action == "database_indexes":
return check_database_indexes(con, database, warning, critical, perf_data) return check_database_indexes(con, database, warning, critical, perf_data)
elif action == "collection_documents":
return check_collection_documents(con, database, collection, warning, critical, perf_data)
elif action == "collection_indexes": elif action == "collection_indexes":
return check_collection_indexes(con, database, collection, warning, critical, perf_data) return check_collection_indexes(con, database, collection, warning, critical, perf_data)
elif action == "collection_size": elif action == "collection_size":
return check_collection_size(con, database, collection, warning, critical, perf_data) return check_collection_size(con, database, collection, warning, critical, perf_data)
elif action == "collection_storageSize":
return check_collection_storageSize(con, database, collection, warning, critical, perf_data)
elif action == "journaled": elif action == "journaled":
return check_journaled(con, warning, critical, perf_data) return check_journaled(con, warning, critical, perf_data)
elif action == "write_data_files": elif action == "write_data_files":
return check_write_to_datafiles(con, warning, critical, perf_data) return check_write_to_datafiles(con, warning, critical, perf_data)
elif action == "opcounters": elif action == "opcounters":
return check_opcounters(con, host, warning, critical, perf_data) return check_opcounters(con, host, port, warning, critical, perf_data)
elif action == "asserts": elif action == "asserts":
return check_asserts(con, host, warning, critical, perf_data) return check_asserts(con, host, port, warning, critical, perf_data)
elif action == "replica_primary": elif action == "replica_primary":
return check_replica_primary(con, host, warning, critical, perf_data, replicaset) return check_replica_primary(con, host, warning, critical, perf_data, replicaset, mongo_version)
elif action == "queries_per_second": elif action == "queries_per_second":
return check_queries_per_second(con, query_type, warning, critical, perf_data) return check_queries_per_second(con, query_type, warning, critical, perf_data, mongo_version)
elif action == "page_faults": elif action == "page_faults":
check_page_faults(con, sample_time, warning, critical, perf_data) check_page_faults(con, sample_time, warning, critical, perf_data)
elif action == "chunks_balance": elif action == "chunks_balance":
@ -255,30 +299,73 @@ def main(argv):
return check_connect(host, port, warning, critical, perf_data, user, passwd, conn_time) return check_connect(host, port, warning, critical, perf_data, user, passwd, conn_time)
def mongo_connect(host=None, port=None, ssl=False, user=None, passwd=None, replica=None): def mongo_connect(host=None, port=None, ssl=False, user=None, passwd=None, replica=None, authdb="admin", insecure=False, ssl_ca_cert_file=None, ssl_cert=None, auth_mechanism=None, retry_writes_disabled=False):
from pymongo.errors import ConnectionFailure
from pymongo.errors import PyMongoError
import ssl as SSL
con_args = dict()
if ssl:
if insecure:
con_args['ssl_cert_reqs'] = SSL.CERT_NONE
else:
con_args['ssl_cert_reqs'] = SSL.CERT_REQUIRED
con_args['ssl'] = ssl
if ssl_ca_cert_file:
con_args['ssl_ca_certs'] = ssl_ca_cert_file
if ssl_cert:
con_args['ssl_certfile'] = ssl_cert
if retry_writes_disabled:
con_args['retryWrites'] = False
try: try:
# ssl connection for pymongo > 2.3 # ssl connection for pymongo > 2.3
if pymongo.version >= "2.3": if pymongo.version >= "2.3":
if replica is None: if replica is None:
con = pymongo.MongoClient(host, port) con = pymongo.MongoClient(host, port, **con_args)
else: else:
con = pymongo.Connection(host, port, read_preference=pymongo.ReadPreference.SECONDARY, ssl=ssl, replicaSet=replica, network_timeout=10) con = pymongo.MongoClient(host, port, read_preference=pymongo.ReadPreference.SECONDARY, replicaSet=replica, **con_args)
else: else:
if replica is None: if replica is None:
con = pymongo.Connection(host, port, slave_okay=True, network_timeout=10) con = pymongo.Connection(host, port, slave_okay=True, network_timeout=10)
else: else:
con = pymongo.Connection(host, port, slave_okay=True, network_timeout=10) con = pymongo.Connection(host, port, slave_okay=True, network_timeout=10)
#con = pymongo.Connection(host, port, slave_okay=True, replicaSet=replica, network_timeout=10)
# we must authenticate the connection, otherwise we won't be able to perform certain operations
if ssl_cert and ssl_ca_cert_file and user and auth_mechanism == 'SCRAM-SHA-256':
con.the_database.authenticate(user, mechanism='SCRAM-SHA-256')
elif ssl_cert and ssl_ca_cert_file and user and auth_mechanism == 'SCRAM-SHA-1':
con.the_database.authenticate(user, mechanism='SCRAM-SHA-1')
elif ssl_cert and ssl_ca_cert_file and user and auth_mechanism == 'MONGODB-X509':
con.the_database.authenticate(user, mechanism='MONGODB-X509')
try:
result = con.admin.command("ismaster")
except ConnectionFailure:
print("CRITICAL - Connection to Mongo server on %s:%s has failed" % (host, port) )
sys.exit(2)
if 'arbiterOnly' in result and result['arbiterOnly'] == True:
print("OK - State: 7 (Arbiter on port %s)" % (port))
sys.exit(0)
if user and passwd: if user and passwd:
db = con["admin"] db = con[authdb]
if not db.authenticate(user, passwd): try:
db.authenticate(user, password=passwd)
except PyMongoError:
sys.exit("Username/Password incorrect") sys.exit("Username/Password incorrect")
except Exception, e:
# Ping to check that the server is responding.
con.admin.command("ping")
except Exception as e:
if isinstance(e, pymongo.errors.AutoReconnect) and str(e).find(" is an arbiter") != -1: if isinstance(e, pymongo.errors.AutoReconnect) and str(e).find(" is an arbiter") != -1:
# We got a pymongo AutoReconnect exception that tells us we connected to an Arbiter Server # We got a pymongo AutoReconnect exception that tells us we connected to an Arbiter Server
# This means: Arbiter is reachable and can answer requests/votes - this is all we need to know from an arbiter # This means: Arbiter is reachable and can answer requests/votes - this is all we need to know from an arbiter
print "OK - State: 7 (Arbiter)" print("OK - State: 7 (Arbiter)")
sys.exit(0) sys.exit(0)
return exit_with_general_critical(e), None return exit_with_general_critical(e), None
return 0, con return 0, con
@ -288,7 +375,7 @@ def exit_with_general_warning(e):
if isinstance(e, SystemExit): if isinstance(e, SystemExit):
return e return e
else: else:
print "WARNING - General MongoDB warning:", e print("WARNING - General MongoDB warning:", e)
return 1 return 1
@ -296,19 +383,27 @@ def exit_with_general_critical(e):
if isinstance(e, SystemExit): if isinstance(e, SystemExit):
return e return e
else: else:
print "CRITICAL - General MongoDB Error:", e print("CRITICAL - General MongoDB Error:", e)
return 2 return 2
def set_read_preference(db): def set_read_preference(db):
if pymongo.version >= "2.1": if pymongo.version >= "2.2":
pymongo.read_preferences.Secondary
else:
db.read_preference = pymongo.ReadPreference.SECONDARY db.read_preference = pymongo.ReadPreference.SECONDARY
def check_version(con):
try:
server_info = con.server_info()
except Exception as e:
return exit_with_general_critical(e), None
return 0, int(server_info['version'].split('.')[0].strip())
def check_connect(host, port, warning, critical, perf_data, user, passwd, conn_time): def check_connect(host, port, warning, critical, perf_data, user, passwd, conn_time):
warning = warning or 3 warning = warning or 3
critical = critical or 6 critical = critical or 6
message = "Connection took %i seconds" % conn_time message = "Connection took %.3f seconds" % conn_time
message += performance_data(perf_data, [(conn_time, "connection_time", warning, critical)]) message += performance_data(perf_data, [(conn_time, "connection_time", warning, critical)])
return check_levels(conn_time, warning, critical, message) return check_levels(conn_time, warning, critical, message)
@ -330,13 +425,17 @@ def check_connections(con, warning, critical, perf_data):
(available, "available_connections")]) (available, "available_connections")])
return check_levels(used_percent, warning, critical, message) return check_levels(used_percent, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
def check_rep_lag(con, host, port, warning, critical, percent, perf_data, max_lag, user, passwd): def check_rep_lag(con, host, port, rdns_lookup, warning, critical, percent, perf_data, max_lag, ssl=False, user=None, passwd=None, replicaset=None, authdb="admin", insecure=None, ssl_ca_cert_file=None, cert_file=None, auth_mechanism=None, retry_writes_disabled=False):
# Get mongo to tell us replica set member name when connecting locally # Get mongo to tell us replica set member name when connecting locally
if "127.0.0.1" == host: if "127.0.0.1" == host:
if not "me" in list(con.admin.command("ismaster","1").keys()):
print("UNKNOWN - This is not replicated MongoDB")
return 3
host = con.admin.command("ismaster","1")["me"].split(':')[0] host = con.admin.command("ismaster","1")["me"].split(':')[0]
if percent: if percent:
@ -348,16 +447,15 @@ def check_rep_lag(con, host, port, warning, critical, percent, perf_data, max_la
rs_status = {} rs_status = {}
slaveDelays = {} slaveDelays = {}
try: try:
set_read_preference(con.admin) #set_read_preference(con.admin)
# Get replica set status # Get replica set status
try: try:
rs_status = con.admin.command("replSetGetStatus") rs_status = con.admin.command("replSetGetStatus")
except pymongo.errors.OperationFailure, e: except pymongo.errors.OperationFailure as e:
if e.code == None and str(e).find('failed: not running with --replSet"'): if ((e.code == None and str(e).find('failed: not running with --replSet"')) or (e.code == 76 and str(e).find('not running with --replSet"'))):
print "OK - Not running with replSet" print("UNKNOWN - Not running with replSet")
return 0 return 3
serverVersion = tuple(con.server_info()['version'].split('.')) serverVersion = tuple(con.server_info()['version'].split('.'))
if serverVersion >= tuple("2.0.0".split(".")): if serverVersion >= tuple("2.0.0".split(".")):
# #
@ -377,24 +475,32 @@ def check_rep_lag(con, host, port, warning, critical, percent, perf_data, max_la
for member in rs_status["members"]: for member in rs_status["members"]:
if member["stateStr"] == "PRIMARY": if member["stateStr"] == "PRIMARY":
primary_node = member primary_node = member
if member["name"].split(':')[0] == host and int(member["name"].split(':')[1]) == port:
# if rdns_lookup is true then lookup both values back to their rdns value so we can compare hostname vs fqdn
if rdns_lookup:
member_host, member_port = split_host_port(member.get('name'))
member_host = "{0}:{1}".format(socket.getnameinfo((member_host, 0), 0)[0], member_port)
if member_host == "{0}:{1}".format(socket.getnameinfo((host, 0), 0)[0], port):
host_node = member
# Exact match
elif member.get('name') == "{0}:{1}".format(host, port):
host_node = member host_node = member
# Check if we're in the middle of an election and don't have a primary # Check if we're in the middle of an election and don't have a primary
if primary_node is None: if primary_node is None:
print "WARNING - No primary defined. In an election?" print("WARNING - No primary defined. In an election?")
return 1 return 1
# Check if we failed to find the current host # Check if we failed to find the current host
# below should never happen # below should never happen
if host_node is None: if host_node is None:
print "CRITICAL - Unable to find host '" + host + "' in replica set." print("CRITICAL - Unable to find host '" + host + "' in replica set.")
return 2 return 2
# Is the specified host the primary? # Is the specified host the primary?
if host_node["stateStr"] == "PRIMARY": if host_node["stateStr"] == "PRIMARY":
if max_lag == False: if max_lag == False:
print "OK - This is the primary." print("OK - This is the primary.")
return 0 return 0
else: else:
#get the maximal replication lag #get the maximal replication lag
@ -407,7 +513,7 @@ def check_rep_lag(con, host, port, warning, critical, percent, perf_data, max_la
data = data + member['name'] + " lag=%d;" % replicationLag data = data + member['name'] + " lag=%d;" % replicationLag
maximal_lag = max(maximal_lag, replicationLag) maximal_lag = max(maximal_lag, replicationLag)
if percent: if percent:
err, con = mongo_connect(primary_node['name'].split(':')[0], int(primary_node['name'].split(':')[1]), False, user, passwd) err, con = mongo_connect(split_host_port(primary_node['name'])[0], int(split_host_port(primary_node['name'])[1]), ssl, user, passwd, replicaset, authdb, insecure, ssl_ca_cert_file, cert_file, auth_mechanism, retry_writes_disabled=retry_writes_disabled)
if err != 0: if err != 0:
return err return err
primary_timediff = replication_get_time_diff(con) primary_timediff = replication_get_time_diff(con)
@ -419,8 +525,8 @@ def check_rep_lag(con, host, port, warning, critical, percent, perf_data, max_la
message += performance_data(perf_data, [(maximal_lag, "replication_lag", warning, critical)]) message += performance_data(perf_data, [(maximal_lag, "replication_lag", warning, critical)])
return check_levels(maximal_lag, warning, critical, message) return check_levels(maximal_lag, warning, critical, message)
elif host_node["stateStr"] == "ARBITER": elif host_node["stateStr"] == "ARBITER":
print "OK - This is an arbiter" print("UNKNOWN - This is an arbiter")
return 0 return 3
# Find the difference in optime between current node and PRIMARY # Find the difference in optime between current node and PRIMARY
@ -439,7 +545,7 @@ def check_rep_lag(con, host, port, warning, critical, percent, perf_data, max_la
lag = float(optime_lag.seconds + optime_lag.days * 24 * 3600) lag = float(optime_lag.seconds + optime_lag.days * 24 * 3600)
if percent: if percent:
err, con = mongo_connect(primary_node['name'].split(':')[0], int(primary_node['name'].split(':')[1]), False, user, passwd) err, con = mongo_connect(split_host_port(primary_node['name'])[0], int(split_host_port(primary_node['name'])[1]), ssl, user, passwd, replicaset, authdb, insecure, ssl_ca_cert_file, cert_file, auth_mechanism, retry_writes_disabled=retry_writes_disabled)
if err != 0: if err != 0:
return err return err
primary_timediff = replication_get_time_diff(con) primary_timediff = replication_get_time_diff(con)
@ -471,19 +577,19 @@ def check_rep_lag(con, host, port, warning, critical, percent, perf_data, max_la
# Check if we're in the middle of an election and don't have a primary # Check if we're in the middle of an election and don't have a primary
if primary_node is None: if primary_node is None:
print "WARNING - No primary defined. In an election?" print("WARNING - No primary defined. In an election?")
sys.exit(1) sys.exit(1)
# Is the specified host the primary? # Is the specified host the primary?
if host_node["stateStr"] == "PRIMARY": if host_node["stateStr"] == "PRIMARY":
print "OK - This is the primary." print("OK - This is the primary.")
sys.exit(0) sys.exit(0)
# Find the difference in optime between current node and PRIMARY # Find the difference in optime between current node and PRIMARY
optime_lag = abs(primary_node[1] - host_node["optimeDate"]) optime_lag = abs(primary_node[1] - host_node["optimeDate"])
lag = optime_lag.seconds lag = optime_lag.seconds
if percent: if percent:
err, con = mongo_connect(primary_node['name'].split(':')[0], int(primary_node['name'].split(':')[1])) err, con = mongo_connect(split_host_port(primary_node['name'])[0], int(split_host_port(primary_node['name'])[1]), ssl, user, passwd, replicaset, authdb, insecure, ssl_ca_cert_file, cert_file, auth_mechanism, retry_writes_disabled=retry_writes_disabled)
if err != 0: if err != 0:
return err return err
primary_timediff = replication_get_time_diff(con) primary_timediff = replication_get_time_diff(con)
@ -495,26 +601,34 @@ def check_rep_lag(con, host, port, warning, critical, percent, perf_data, max_la
message += performance_data(perf_data, [(lag, "replication_lag", warning, critical)]) message += performance_data(perf_data, [(lag, "replication_lag", warning, critical)])
return check_levels(lag, warning, critical, message) return check_levels(lag, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
#
def check_memory(con, warning, critical, perf_data, mapped_memory): # Check the memory usage of mongo. Alerting on this may be hard to get right
# # because it'll try to get as much memory as it can. And that's probably
# These thresholds are basically meaningless, and must be customized to your system's ram # a good thing.
# #
def check_memory(con, warning, critical, perf_data, mapped_memory, host):
# Get the total system merory and calculate based on that how much memory used by Mongodb is ok or not. # Get the total system memory of this system (This is totally bogus if you
# are running this command remotely) and calculate based on that how much
# memory used by Mongodb is ok or not.
meminfo = open('/proc/meminfo').read() meminfo = open('/proc/meminfo').read()
matched = re.search(r'^MemTotal:\s+(\d+)', meminfo) matched = re.search(r'^MemTotal:\s+(\d+)', meminfo)
if matched: if matched:
mem_total_kB = int(matched.groups()[0]) mem_total_kB = int(matched.groups()[0])
# Old way if host != "127.0.0.1" and not warning:
#critical = critical or 16 # Running remotely and value was not set by user, use hardcoded value
# The new way. if using >80% then warn, if >90% then critical level warning = 12
warning = warning or (mem_total_kB * 0.8) / 1024.0 / 1024.0 else:
critical = critical or (mem_total_kB * 0.9) / 1024.0 / 1024.0 # running locally or user provided value
warning = warning or (mem_total_kB * 0.8) / 1024.0 / 1024.0
if host != "127.0.0.1" and not critical:
critical = 16
else:
critical = critical or (mem_total_kB * 0.9) / 1024.0 / 1024.0
# debugging # debugging
#print "mem total: {0}kb, warn: {1}GB, crit: {2}GB".format(mem_total_kB,warning, critical) #print "mem total: {0}kb, warn: {1}GB, crit: {2}GB".format(mem_total_kB,warning, critical)
@ -522,7 +636,7 @@ def check_memory(con, warning, critical, perf_data, mapped_memory):
try: try:
data = get_server_status(con) data = get_server_status(con)
if not data['mem']['supported'] and not mapped_memory: if not data['mem']['supported'] and not mapped_memory:
print "OK - Platform not supported for memory info" print("OK - Platform not supported for memory info")
return 0 return 0
# #
# convert to gigs # convert to gigs
@ -559,7 +673,7 @@ def check_memory(con, warning, critical, perf_data, mapped_memory):
else: else:
return check_levels(mem_resident, warning, critical, message) return check_levels(mem_resident, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
@ -572,7 +686,7 @@ def check_memory_mapped(con, warning, critical, perf_data):
try: try:
data = get_server_status(con) data = get_server_status(con)
if not data['mem']['supported']: if not data['mem']['supported']:
print "OK - Platform not supported for memory info" print("OK - Platform not supported for memory info")
return 0 return 0
# #
# convert to gigs # convert to gigs
@ -589,38 +703,45 @@ def check_memory_mapped(con, warning, critical, perf_data):
message += " %.2fGB mappedWithJournal" % mem_mapped_journal message += " %.2fGB mappedWithJournal" % mem_mapped_journal
except: except:
mem_mapped_journal = 0 mem_mapped_journal = 0
message += performance_data(perf_data, [("%.2f" % mem_mapped, "memory_mapped"), ("%.2f" % mem_mapped_journal, "mappedWithJournal")]) message += performance_data(perf_data, [("%.2f" % mem_mapped, "memory_mapped", warning, critical), ("%.2f" % mem_mapped_journal, "mappedWithJournal")])
if not mem_mapped == -1: if not mem_mapped == -1:
return check_levels(mem_mapped, warning, critical, message) return check_levels(mem_mapped, warning, critical, message)
else: else:
print "OK - Server does not provide mem.mapped info" print("OK - Server does not provide mem.mapped info")
return 0 return 0
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
def check_lock(con, warning, critical, perf_data): #
# Return the percentage of the time there was a global Lock
#
def check_lock(con, warning, critical, perf_data, mongo_version):
warning = warning or 10 warning = warning or 10
critical = critical or 30 critical = critical or 30
try: if mongo_version == 2:
data = get_server_status(con) try:
# data = get_server_status(con)
# calculate percentage lockTime = data['globalLock']['lockTime']
# totalTime = data['globalLock']['totalTime']
lockTime = data['globalLock']['lockTime'] #
totalTime = data['globalLock']['totalTime'] # calculate percentage
if lockTime > totalTime: #
lock_percentage = 0.00 if lockTime > totalTime:
else: lock_percentage = 0.00
lock_percentage = float(lockTime) / float(totalTime) * 100 else:
message = "Lock Percentage: %.2f%%" % lock_percentage lock_percentage = float(lockTime) / float(totalTime) * 100
message += performance_data(perf_data, [("%.2f" % lock_percentage, "lock_percentage", warning, critical)]) message = "Lock Percentage: %.2f%%" % lock_percentage
return check_levels(lock_percentage, warning, critical, message) message += performance_data(perf_data, [("%.2f" % lock_percentage, "lock_percentage", warning, critical)])
return check_levels(lock_percentage, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) print("Couldn't get globalLock lockTime info from mongo, are you sure you're not using version 3? See the -M option.")
return exit_with_general_critical(e)
else:
print("OK - MongoDB version 3 doesn't report on global locks")
return 0
def check_flushing(con, warning, critical, avg, perf_data): def check_flushing(con, warning, critical, avg, perf_data):
@ -632,19 +753,24 @@ def check_flushing(con, warning, critical, avg, perf_data):
critical = critical or 15000 critical = critical or 15000
try: try:
data = get_server_status(con) data = get_server_status(con)
if avg: try:
flush_time = float(data['backgroundFlushing']['average_ms']) data['backgroundFlushing']
stat_type = "Average" if avg:
else: flush_time = float(data['backgroundFlushing']['average_ms'])
flush_time = float(data['backgroundFlushing']['last_ms']) stat_type = "Average"
stat_type = "Last" else:
flush_time = float(data['backgroundFlushing']['last_ms'])
stat_type = "Last"
message = "%s Flush Time: %.2fms" % (stat_type, flush_time) message = "%s Flush Time: %.2fms" % (stat_type, flush_time)
message += performance_data(perf_data, [("%.2fms" % flush_time, "%s_flush_time" % stat_type.lower(), warning, critical)]) message += performance_data(perf_data, [("%.2fms" % flush_time, "%s_flush_time" % stat_type.lower(), warning, critical)])
return check_levels(flush_time, warning, critical, message) return check_levels(flush_time, warning, critical, message)
except Exception:
print("OK - flushing stats not available for this storage engine")
return 0
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
@ -655,6 +781,7 @@ def index_miss_ratio(con, warning, critical, perf_data):
data = get_server_status(con) data = get_server_status(con)
try: try:
data['indexCounters']
serverVersion = tuple(con.server_info()['version'].split('.')) serverVersion = tuple(con.server_info()['version'].split('.'))
if serverVersion >= tuple("2.4.0".split(".")): if serverVersion >= tuple("2.4.0".split(".")):
miss_ratio = float(data['indexCounters']['missRatio']) miss_ratio = float(data['indexCounters']['missRatio'])
@ -662,19 +789,24 @@ def index_miss_ratio(con, warning, critical, perf_data):
miss_ratio = float(data['indexCounters']['btree']['missRatio']) miss_ratio = float(data['indexCounters']['btree']['missRatio'])
except KeyError: except KeyError:
not_supported_msg = "not supported on this platform" not_supported_msg = "not supported on this platform"
if data['indexCounters'].has_key('note'): try:
print "OK - MongoDB says: " + not_supported_msg data['indexCounters']
if 'note' in data['indexCounters']:
print("OK - MongoDB says: " + not_supported_msg)
return 0
else:
print("WARNING - Can't get counter from MongoDB")
return 1
except Exception:
print("OK - MongoDB says: " + not_supported_msg)
return 0 return 0
else:
print "WARNING - Can't get counter from MongoDB"
return 1
message = "Miss Ratio: %.2f" % miss_ratio message = "Miss Ratio: %.2f" % miss_ratio
message += performance_data(perf_data, [("%.2f" % miss_ratio, "index_miss_ratio", warning, critical)]) message += performance_data(perf_data, [("%.2f" % miss_ratio, "index_miss_ratio", warning, critical)])
return check_levels(miss_ratio, warning, critical, message) return check_levels(miss_ratio, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
def check_replset_quorum(con, perf_data): def check_replset_quorum(con, perf_data):
@ -698,7 +830,7 @@ def check_replset_quorum(con, perf_data):
message = "Cluster is not quorate and cannot operate" message = "Cluster is not quorate and cannot operate"
return check_levels(state, warning, critical, message) return check_levels(state, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
@ -713,44 +845,63 @@ def check_replset_state(con, perf_data, warning="", critical=""):
except: except:
critical = [8, 4, -1] critical = [8, 4, -1]
ok = range(-1, 8) # should include the range of all posiible values ok = list(range(-1, 8)) # should include the range of all posiible values
try: try:
worst_state = -2
message = ""
try: try:
try: try:
set_read_preference(con.admin) set_read_preference(con.admin)
data = con.admin.command(pymongo.son_manipulator.SON([('replSetGetStatus', 1)])) data = con.admin.command(pymongo.son_manipulator.SON([('replSetGetStatus', 1)]))
except: except:
data = con.admin.command(son.SON([('replSetGetStatus', 1)])) data = con.admin.command(son.SON([('replSetGetStatus', 1)]))
state = int(data['myState']) members = data['members']
except pymongo.errors.OperationFailure, e: my_state = int(data['myState'])
if e.code == None and str(e).find('failed: not running with --replSet"'): worst_state = my_state
state = -1 for member in members:
their_state = int(member['state'])
message += " %s: %i (%s)" % (member['name'], their_state, state_text(their_state))
if state_is_worse(their_state, worst_state, warning, critical):
worst_state = their_state
message += performance_data(perf_data, [(my_state, "state")])
if state == 8: except pymongo.errors.OperationFailure as e:
message = "State: %i (Down)" % state if ((e.code == None and str(e).find('failed: not running with --replSet"')) or (e.code == 76 and str(e).find('not running with --replSet"'))):
elif state == 4: worst_state = -1
message = "State: %i (Fatal error)" % state
elif state == 0: return check_levels(worst_state, warning, critical, message, ok)
message = "State: %i (Starting up, phase1)" % state except Exception as e:
elif state == 3:
message = "State: %i (Recovering)" % state
elif state == 5:
message = "State: %i (Starting up, phase2)" % state
elif state == 1:
message = "State: %i (Primary)" % state
elif state == 2:
message = "State: %i (Secondary)" % state
elif state == 7:
message = "State: %i (Arbiter)" % state
elif state == -1:
message = "Not running with replSet"
else:
message = "State: %i (Unknown state)" % state
message += performance_data(perf_data, [(state, "state")])
return check_levels(state, warning, critical, message, ok)
except Exception, e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
def state_is_worse(state, worst_state, warning, critical):
if worst_state in critical:
return False
if worst_state in warning:
return state in critical
return (state in warning) or (state in critical)
def state_text(state):
if state == 8:
return "Down"
elif state == 4:
return "Fatal error"
elif state == 0:
return "Starting up, phase1"
elif state == 3:
return "Recovering"
elif state == 5:
return "Starting up, phase2"
elif state == 1:
return "Primary"
elif state == 2:
return "Secondary"
elif state == 7:
return "Arbiter"
elif state == -1:
return "Not running with replSet"
else:
return "Unknown state"
def check_databases(con, warning, critical, perf_data=None): def check_databases(con, warning, critical, perf_data=None):
try: try:
@ -764,7 +915,7 @@ def check_databases(con, warning, critical, perf_data=None):
message = "Number of DBs: %.0f" % count message = "Number of DBs: %.0f" % count
message += performance_data(perf_data, [(count, "databases", warning, critical, message)]) message += performance_data(perf_data, [(count, "databases", warning, critical, message)])
return check_levels(count, warning, critical, message) return check_levels(count, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
@ -786,7 +937,7 @@ def check_collections(con, warning, critical, perf_data=None):
message += performance_data(perf_data, [(count, "collections", warning, critical, message)]) message += performance_data(perf_data, [(count, "collections", warning, critical, message)])
return check_levels(count, warning, critical, message) return check_levels(count, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
@ -823,21 +974,21 @@ def check_database_size(con, database, warning, critical, perf_data):
try: try:
set_read_preference(con.admin) set_read_preference(con.admin)
data = con[database].command('dbstats') data = con[database].command('dbstats')
storage_size = data['storageSize'] / 1024 / 1024 storage_size = data['storageSize'] // 1024 // 1024
if perf_data: if perf_data:
perfdata += " | database_size=%i;%i;%i" % (storage_size, warning, critical) perfdata += " | database_size=%i;%i;%i" % (storage_size, warning, critical)
#perfdata += " database=%s" %(database) #perfdata += " database=%s" %(database)
if storage_size >= critical: if storage_size >= critical:
print "CRITICAL - Database size: %.0f MB, Database: %s%s" % (storage_size, database, perfdata) print("CRITICAL - Database size: %.0f MB, Database: %s%s" % (storage_size, database, perfdata))
return 2 return 2
elif storage_size >= warning: elif storage_size >= warning:
print "WARNING - Database size: %.0f MB, Database: %s%s" % (storage_size, database, perfdata) print("WARNING - Database size: %.0f MB, Database: %s%s" % (storage_size, database, perfdata))
return 1 return 1
else: else:
print "OK - Database size: %.0f MB, Database: %s%s" % (storage_size, database, perfdata) print("OK - Database size: %.0f MB, Database: %s%s" % (storage_size, database, perfdata))
return 0 return 0
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
@ -851,20 +1002,42 @@ def check_database_indexes(con, database, warning, critical, perf_data):
try: try:
set_read_preference(con.admin) set_read_preference(con.admin)
data = con[database].command('dbstats') data = con[database].command('dbstats')
index_size = data['indexSize'] / 1024 / 1024 index_size = data['indexSize'] / 1024 // 1024
if perf_data: if perf_data:
perfdata += " | database_indexes=%i;%i;%i" % (index_size, warning, critical) perfdata += " | database_indexes=%i;%i;%i" % (index_size, warning, critical)
if index_size >= critical: if index_size >= critical:
print "CRITICAL - %s indexSize: %.0f MB %s" % (database, index_size, perfdata) print("CRITICAL - %s indexSize: %.0f MB %s" % (database, index_size, perfdata))
return 2 return 2
elif index_size >= warning: elif index_size >= warning:
print "WARNING - %s indexSize: %.0f MB %s" % (database, index_size, perfdata) print("WARNING - %s indexSize: %.0f MB %s" % (database, index_size, perfdata))
return 1 return 1
else: else:
print "OK - %s indexSize: %.0f MB %s" % (database, index_size, perfdata) print("OK - %s indexSize: %.0f MB %s" % (database, index_size, perfdata))
return 0 return 0
except Exception, e: except Exception as e:
return exit_with_general_critical(e)
def check_collection_documents(con, database, collection, warning, critical, perf_data):
perfdata = ""
try:
set_read_preference(con.admin)
data = con[database].command('collstats', collection)
documents = data['count']
if perf_data:
perfdata += " | collection_documents=%i;%i;%i" % (documents, warning, critical)
if documents >= critical:
print("CRITICAL - %s.%s documents: %s %s" % (database, collection, documents, perfdata))
return 2
elif documents >= warning:
print("WARNING - %s.%s documents: %s %s" % (database, collection, documents, perfdata))
return 1
else:
print("OK - %s.%s documents: %s %s" % (database, collection, documents, perfdata))
return 0
except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
@ -883,15 +1056,15 @@ def check_collection_indexes(con, database, collection, warning, critical, perf_
perfdata += " | collection_indexes=%i;%i;%i" % (total_index_size, warning, critical) perfdata += " | collection_indexes=%i;%i;%i" % (total_index_size, warning, critical)
if total_index_size >= critical: if total_index_size >= critical:
print "CRITICAL - %s.%s totalIndexSize: %.0f MB %s" % (database, collection, total_index_size, perfdata) print("CRITICAL - %s.%s totalIndexSize: %.0f MB %s" % (database, collection, total_index_size, perfdata))
return 2 return 2
elif total_index_size >= warning: elif total_index_size >= warning:
print "WARNING - %s.%s totalIndexSize: %.0f MB %s" % (database, collection, total_index_size, perfdata) print("WARNING - %s.%s totalIndexSize: %.0f MB %s" % (database, collection, total_index_size, perfdata))
return 1 return 1
else: else:
print "OK - %s.%s totalIndexSize: %.0f MB %s" % (database, collection, total_index_size, perfdata) print("OK - %s.%s totalIndexSize: %.0f MB %s" % (database, collection, total_index_size, perfdata))
return 0 return 0
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
@ -908,7 +1081,7 @@ def check_queues(con, warning, critical, perf_data):
message += performance_data(perf_data, [(total_queues, "total_queues", warning, critical), (readers_queues, "readers_queues"), (writers_queues, "writers_queues")]) message += performance_data(perf_data, [(total_queues, "total_queues", warning, critical), (readers_queues, "readers_queues"), (writers_queues, "writers_queues")])
return check_levels(total_queues, warning, critical, message) return check_levels(total_queues, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
def check_collection_size(con, database, collection, warning, critical, perf_data): def check_collection_size(con, database, collection, warning, critical, perf_data):
@ -923,18 +1096,43 @@ def check_collection_size(con, database, collection, warning, critical, perf_dat
perfdata += " | collection_size=%i;%i;%i" % (size, warning, critical) perfdata += " | collection_size=%i;%i;%i" % (size, warning, critical)
if size >= critical: if size >= critical:
print "CRITICAL - %s.%s size: %.0f MB %s" % (database, collection, size, perfdata) print("CRITICAL - %s.%s size: %.0f MB %s" % (database, collection, size, perfdata))
return 2 return 2
elif size >= warning: elif size >= warning:
print "WARNING - %s.%s size: %.0f MB %s" % (database, collection, size, perfdata) print("WARNING - %s.%s size: %.0f MB %s" % (database, collection, size, perfdata))
return 1 return 1
else: else:
print "OK - %s.%s size: %.0f MB %s" % (database, collection, size, perfdata) print("OK - %s.%s size: %.0f MB %s" % (database, collection, size, perfdata))
return 0 return 0
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
def check_queries_per_second(con, query_type, warning, critical, perf_data):
def check_collection_storageSize(con, database, collection, warning, critical, perf_data):
warning = warning or 100
critical = critical or 1000
perfdata = ""
try:
set_read_preference(con.admin)
data = con[database].command('collstats', collection)
storageSize = data['storageSize'] / 1024 / 1024
if perf_data:
perfdata += " | collection_storageSize=%i;%i;%i" % (storageSize, warning, critical)
if storageSize >= critical:
print("CRITICAL - %s.%s storageSize: %.0f MB %s" % (database, collection, storageSize, perfdata))
return 2
elif storageSize >= warning:
print("WARNING - %s.%s storageSize: %.0f MB %s" % (database, collection, storageSize, perfdata))
return 1
else:
print("OK - %s.%s storageSize: %.0f MB %s" % (database, collection, storageSize, perfdata))
return 0
except Exception as e:
return exit_with_general_critical(e)
def check_queries_per_second(con, query_type, warning, critical, perf_data, mongo_version):
warning = warning or 250 warning = warning or 250
critical = critical or 500 critical = critical or 500
@ -955,10 +1153,17 @@ def check_queries_per_second(con, query_type, warning, critical, perf_data):
diff_query = num - last_count['data'][query_type]['count'] diff_query = num - last_count['data'][query_type]['count']
diff_ts = ts - last_count['data'][query_type]['ts'] diff_ts = ts - last_count['data'][query_type]['ts']
if diff_ts == 0:
message = "diff_query = " + str(diff_query) + " diff_ts = " + str(diff_ts)
return check_levels(0, warning, critical, message)
query_per_sec = float(diff_query) / float(diff_ts) query_per_sec = float(diff_query) / float(diff_ts)
# update the count now # update the count now
db.nagios_check.update({u'_id': last_count['_id']}, {'$set': {"data.%s" % query_type: {'count': num, 'ts': int(time.time())}}}) if mongo_version == 2:
db.nagios_check.update({u'_id': last_count['_id']}, {'$set': {"data.%s" % query_type: {'count': num, 'ts': int(time.time())}}})
else:
db.nagios_check.update_one({u'_id': last_count['_id']}, {'$set': {"data.%s" % query_type: {'count': num, 'ts': int(time.time())}}})
message = "Queries / Sec: %f" % query_per_sec message = "Queries / Sec: %f" % query_per_sec
message += performance_data(perf_data, [(query_per_sec, "%s_per_sec" % query_type, warning, critical, message)]) message += performance_data(perf_data, [(query_per_sec, "%s_per_sec" % query_type, warning, critical, message)])
@ -967,17 +1172,24 @@ def check_queries_per_second(con, query_type, warning, critical, perf_data):
# since it is the first run insert it # since it is the first run insert it
query_per_sec = 0 query_per_sec = 0
message = "First run of check.. no data" message = "First run of check.. no data"
db.nagios_check.update({u'_id': last_count['_id']}, {'$set': {"data.%s" % query_type: {'count': num, 'ts': int(time.time())}}}) if mongo_version == 2:
db.nagios_check.update({u'_id': last_count['_id']}, {'$set': {"data.%s" % query_type: {'count': num, 'ts': int(time.time())}}})
else:
db.nagios_check.update_one({u'_id': last_count['_id']}, {'$set': {"data.%s" % query_type: {'count': num, 'ts': int(time.time())}}})
except TypeError: except TypeError:
# #
# since it is the first run insert it # since it is the first run insert it
query_per_sec = 0 query_per_sec = 0
message = "First run of check.. no data" message = "First run of check.. no data"
db.nagios_check.insert({'check': 'query_counts', 'data': {query_type: {'count': num, 'ts': int(time.time())}}}) if mongo_version == 2:
db.nagios_check.insert({'check': 'query_counts', 'data': {query_type: {'count': num, 'ts': int(time.time())}}})
else:
db.nagios_check.insert_one({'check': 'query_counts', 'data': {query_type: {'count': num, 'ts': int(time.time())}}})
return check_levels(query_per_sec, warning, critical, message) return check_levels(query_per_sec, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
@ -1024,7 +1236,7 @@ def check_oplog(con, warning, critical, perf_data):
message += performance_data(perf_data, [("%.2f" % hours_in_oplog, 'oplog_time', warning, critical), ("%.2f " % approx_level, 'oplog_time_100_percent_used')]) message += performance_data(perf_data, [("%.2f" % hours_in_oplog, 'oplog_time', warning, critical), ("%.2f " % approx_level, 'oplog_time_100_percent_used')])
return check_levels(-approx_level, -warning, -critical, message) return check_levels(-approx_level, -warning, -critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
@ -1042,7 +1254,7 @@ Under very high write situations it is normal for this value to be nonzero. """
message += performance_data(perf_data, [(j_commits_in_wl, "j_commits_in_wl", warning, critical)]) message += performance_data(perf_data, [(j_commits_in_wl, "j_commits_in_wl", warning, critical)])
return check_levels(j_commits_in_wl, warning, critical, message) return check_levels(j_commits_in_wl, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
@ -1058,7 +1270,7 @@ def check_journaled(con, warning, critical, perf_data):
message += performance_data(perf_data, [("%.2f" % journaled, "journaled", warning, critical)]) message += performance_data(perf_data, [("%.2f" % journaled, "journaled", warning, critical)])
return check_levels(journaled, warning, critical, message) return check_levels(journaled, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
@ -1075,11 +1287,11 @@ than the amount physically written to disk."""
message += performance_data(perf_data, [("%.2f" % writes, "write_to_data_files", warning, critical)]) message += performance_data(perf_data, [("%.2f" % writes, "write_to_data_files", warning, critical)])
return check_levels(writes, warning, critical, message) return check_levels(writes, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
def get_opcounters(data, opcounters_name, host): def get_opcounters(data, opcounters_name, host, port):
try: try:
insert = data[opcounters_name]['insert'] insert = data[opcounters_name]['insert']
query = data[opcounters_name]['query'] query = data[opcounters_name]['query']
@ -1087,21 +1299,21 @@ def get_opcounters(data, opcounters_name, host):
delete = data[opcounters_name]['delete'] delete = data[opcounters_name]['delete']
getmore = data[opcounters_name]['getmore'] getmore = data[opcounters_name]['getmore']
command = data[opcounters_name]['command'] command = data[opcounters_name]['command']
except KeyError, e: except KeyError as e:
return 0, [0] * 100 return 0, [0] * 100
total_commands = insert + query + update + delete + getmore + command total_commands = insert + query + update + delete + getmore + command
new_vals = [total_commands, insert, query, update, delete, getmore, command] new_vals = [total_commands, insert, query, update, delete, getmore, command]
return maintain_delta(new_vals, host, opcounters_name) return maintain_delta(new_vals, host, port, opcounters_name)
def check_opcounters(con, host, warning, critical, perf_data): def check_opcounters(con, host, port, warning, critical, perf_data):
""" A function to get all opcounters delta per minute. In case of a replication - gets the opcounters+opcountersRepl""" """ A function to get all opcounters delta per minute. In case of a replication - gets the opcounters+opcountersRepl"""
warning = warning or 10000 warning = warning or 10000
critical = critical or 15000 critical = critical or 15000
data = get_server_status(con) data = get_server_status(con)
err1, delta_opcounters = get_opcounters(data, 'opcounters', host) err1, delta_opcounters = get_opcounters(data, 'opcounters', host, port)
err2, delta_opcounters_repl = get_opcounters(data, 'opcountersRepl', host) err2, delta_opcounters_repl = get_opcounters(data, 'opcountersRepl', host, port)
if err1 == 0 and err2 == 0: if err1 == 0 and err2 == 0:
delta = [(x + y) for x, y in zip(delta_opcounters, delta_opcounters_repl)] delta = [(x + y) for x, y in zip(delta_opcounters, delta_opcounters_repl)]
delta[0] = delta_opcounters[0] # only the time delta shouldn't be summarized delta[0] = delta_opcounters[0] # only the time delta shouldn't be summarized
@ -1109,14 +1321,14 @@ def check_opcounters(con, host, warning, critical, perf_data):
message = "Test succeeded , old values missing" message = "Test succeeded , old values missing"
message = "Opcounters: total=%d,insert=%d,query=%d,update=%d,delete=%d,getmore=%d,command=%d" % tuple(per_minute_delta) message = "Opcounters: total=%d,insert=%d,query=%d,update=%d,delete=%d,getmore=%d,command=%d" % tuple(per_minute_delta)
message += performance_data(perf_data, ([(per_minute_delta[0], "total", warning, critical), (per_minute_delta[1], "insert"), message += performance_data(perf_data, ([(per_minute_delta[0], "total", warning, critical), (per_minute_delta[1], "insert"),
(per_minute_delta[2], "query"), (per_minute_delta[3], "update"), (per_minute_delta[5], "delete"), (per_minute_delta[2], "query"), (per_minute_delta[3], "update"), (per_minute_delta[4], "delete"),
(per_minute_delta[5], "getmore"), (per_minute_delta[6], "command")])) (per_minute_delta[5], "getmore"), (per_minute_delta[6], "command")]))
return check_levels(per_minute_delta[0], warning, critical, message) return check_levels(per_minute_delta[0], warning, critical, message)
else: else:
return exit_with_general_critical("problem reading data from temp file") return exit_with_general_critical("problem reading data from temp file")
def check_current_lock(con, host, warning, critical, perf_data): def check_current_lock(con, host, port, warning, critical, perf_data):
""" A function to get current lock percentage and not a global one, as check_lock function does""" """ A function to get current lock percentage and not a global one, as check_lock function does"""
warning = warning or 10 warning = warning or 10
critical = critical or 30 critical = critical or 30
@ -1125,7 +1337,7 @@ def check_current_lock(con, host, warning, critical, perf_data):
lockTime = float(data['globalLock']['lockTime']) lockTime = float(data['globalLock']['lockTime'])
totalTime = float(data['globalLock']['totalTime']) totalTime = float(data['globalLock']['totalTime'])
err, delta = maintain_delta([totalTime, lockTime], host, "locktime") err, delta = maintain_delta([totalTime, lockTime], host, port, "locktime")
if err == 0: if err == 0:
lock_percentage = delta[2] / delta[1] * 100 # lockTime/totalTime*100 lock_percentage = delta[2] / delta[1] * 100 # lockTime/totalTime*100
message = "Current Lock Percentage: %.2f%%" % lock_percentage message = "Current Lock Percentage: %.2f%%" % lock_percentage
@ -1135,7 +1347,7 @@ def check_current_lock(con, host, warning, critical, perf_data):
return exit_with_general_warning("problem reading data from temp file") return exit_with_general_warning("problem reading data from temp file")
def check_page_faults(con, host, warning, critical, perf_data): def check_page_faults(con, host, port, warning, critical, perf_data):
""" A function to get page_faults per second from the system""" """ A function to get page_faults per second from the system"""
warning = warning or 10 warning = warning or 10
critical = critical or 30 critical = critical or 30
@ -1147,7 +1359,7 @@ def check_page_faults(con, host, warning, critical, perf_data):
# page_faults unsupported on the underlaying system # page_faults unsupported on the underlaying system
return exit_with_general_critical("page_faults unsupported on the underlaying system") return exit_with_general_critical("page_faults unsupported on the underlaying system")
err, delta = maintain_delta([page_faults], host, "page_faults") err, delta = maintain_delta([page_faults], host, port, "page_faults")
if err == 0: if err == 0:
page_faults_ps = delta[1] / delta[0] page_faults_ps = delta[1] / delta[0]
message = "Page faults : %.2f ps" % page_faults_ps message = "Page faults : %.2f ps" % page_faults_ps
@ -1157,7 +1369,7 @@ def check_page_faults(con, host, warning, critical, perf_data):
return exit_with_general_warning("problem reading data from temp file") return exit_with_general_warning("problem reading data from temp file")
def check_asserts(con, host, warning, critical, perf_data): def check_asserts(con, host, port, warning, critical, perf_data):
""" A function to get asserts from the system""" """ A function to get asserts from the system"""
warning = warning or 1 warning = warning or 1
critical = critical or 10 critical = critical or 10
@ -1172,7 +1384,7 @@ def check_asserts(con, host, warning, critical, perf_data):
user = asserts['user'] user = asserts['user']
rollovers = asserts['rollovers'] rollovers = asserts['rollovers']
err, delta = maintain_delta([regular, warning_asserts, msg, user, rollovers], host, "asserts") err, delta = maintain_delta([regular, warning_asserts, msg, user, rollovers], host, port, "asserts")
if err == 0: if err == 0:
if delta[5] != 0: if delta[5] != 0:
@ -1206,7 +1418,7 @@ def get_stored_primary_server_name(db):
return stored_primary_server return stored_primary_server
def check_replica_primary(con, host, warning, critical, perf_data, replicaset): def check_replica_primary(con, host, warning, critical, perf_data, replicaset, mongo_version):
""" A function to check if the primary server of a replica set has changed """ """ A function to check if the primary server of a replica set has changed """
if warning is None and critical is None: if warning is None and critical is None:
warning = 1 warning = 1
@ -1229,7 +1441,10 @@ def check_replica_primary(con, host, warning, critical, perf_data, replicaset):
saved_primary = "None" saved_primary = "None"
if current_primary != saved_primary: if current_primary != saved_primary:
last_primary_server_record = {"server": current_primary} last_primary_server_record = {"server": current_primary}
db.last_primary_server.update({"_id": "last_primary"}, {"$set": last_primary_server_record}, upsert=True, safe=True) if mongo_version == 2:
db.last_primary_server.update({"_id": "last_primary"}, {"$set": last_primary_server_record}, upsert=True)
else:
db.last_primary_server.update_one({"_id": "last_primary"}, {"$set": last_primary_server_record}, upsert=True)
message = "Primary server has changed from %s to %s" % (saved_primary, current_primary) message = "Primary server has changed from %s to %s" % (saved_primary, current_primary)
primary_status = 1 primary_status = 1
return check_levels(primary_status, warning, critical, message) return check_levels(primary_status, warning, critical, message)
@ -1251,9 +1466,9 @@ def check_page_faults(con, sample_time, warning, critical, perf_data):
try: try:
#on linux servers only #on linux servers only
page_faults = (int(data2['extra_info']['page_faults']) - int(data1['extra_info']['page_faults'])) / sample_time page_faults = (int(data2['extra_info']['page_faults']) - int(data1['extra_info']['page_faults'])) // sample_time
except KeyError: except KeyError:
print "WARNING - Can't get extra_info.page_faults counter from MongoDB" print("WARNING - Can't get extra_info.page_faults counter from MongoDB")
sys.exit(1) sys.exit(1)
message = "Page Faults: %i" % (page_faults) message = "Page Faults: %i" % (page_faults)
@ -1261,7 +1476,7 @@ def check_page_faults(con, sample_time, warning, critical, perf_data):
message += performance_data(perf_data, [(page_faults, "page_faults", warning, critical)]) message += performance_data(perf_data, [(page_faults, "page_faults", warning, critical)])
check_levels(page_faults, warning, critical, message) check_levels(page_faults, warning, critical, message)
except Exception, e: except Exception as e:
exit_with_general_critical(e) exit_with_general_critical(e)
@ -1277,35 +1492,35 @@ def chunks_balance(con, database, collection, warning, critical):
shards = col.distinct("shard") shards = col.distinct("shard")
except: except:
print "WARNING - Can't get chunks infos from MongoDB" print("WARNING - Can't get chunks infos from MongoDB")
sys.exit(1) sys.exit(1)
if nscount == 0: if nscount == 0:
print "WARNING - Namespace %s is not sharded" % (nsfilter) print("WARNING - Namespace %s is not sharded" % (nsfilter))
sys.exit(1) sys.exit(1)
avgchunksnb = nscount / len(shards) avgchunksnb = nscount // len(shards)
warningnb = avgchunksnb * warning / 100 warningnb = avgchunksnb * warning // 100
criticalnb = avgchunksnb * critical / 100 criticalnb = avgchunksnb * critical // 100
for shard in shards: for shard in shards:
delta = abs(avgchunksnb - col.find({"ns": nsfilter, "shard": shard}).count()) delta = abs(avgchunksnb - col.find({"ns": nsfilter, "shard": shard}).count())
message = "Namespace: %s, Shard name: %s, Chunk delta: %i" % (nsfilter, shard, delta) message = "Namespace: %s, Shard name: %s, Chunk delta: %i" % (nsfilter, shard, delta)
if delta >= criticalnb and delta > 0: if delta >= criticalnb and delta > 0:
print "CRITICAL - Chunks not well balanced " + message print("CRITICAL - Chunks not well balanced " + message)
sys.exit(2) sys.exit(2)
elif delta >= warningnb and delta > 0: elif delta >= warningnb and delta > 0:
print "WARNING - Chunks not well balanced " + message print("WARNING - Chunks not well balanced " + message)
sys.exit(1) sys.exit(1)
print "OK - Chunks well balanced across shards" print("OK - Chunks well balanced across shards")
sys.exit(0) sys.exit(0)
except Exception, e: except Exception as e:
exit_with_general_critical(e) exit_with_general_critical(e)
print "OK - Chunks well balanced across shards" print("OK - Chunks well balanced across shards")
sys.exit(0) sys.exit(0)
@ -1321,7 +1536,7 @@ def check_connect_primary(con, warning, critical, perf_data):
data = con.admin.command(son.SON([('isMaster', 1)])) data = con.admin.command(son.SON([('isMaster', 1)]))
if data['ismaster'] == True: if data['ismaster'] == True:
print "OK - This server is primary" print("OK - This server is primary")
return 0 return 0
phost = data['primary'].split(':')[0] phost = data['primary'].split(':')[0]
@ -1339,17 +1554,17 @@ def check_connect_primary(con, warning, critical, perf_data):
return check_levels(pconn_time, warning, critical, message) return check_levels(pconn_time, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
def check_collection_state(con, database, collection): def check_collection_state(con, database, collection):
try: try:
con[database][collection].find_one() con[database][collection].find_one()
print "OK - Collection %s.%s is reachable " % (database, collection) print("OK - Collection %s.%s is reachable " % (database, collection))
return 0 return 0
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
@ -1361,14 +1576,18 @@ def check_row_count(con, database, collection, warning, critical, perf_data):
return check_levels(count, warning, critical, message) return check_levels(count, warning, critical, message)
except Exception, e: except Exception as e:
return exit_with_general_critical(e) return exit_with_general_critical(e)
def build_file_name(host, action): def build_file_name(host, port, action):
#done this way so it will work when run independently and from shell #done this way so it will work when run independently and from shell
module_name = re.match('(.*//*)*(.*)\..*', __file__).group(2) module_name = re.match('(.*//*)*(.*)\..*', __file__).group(2)
return "/tmp/" + module_name + "_data/" + host + "-" + action + ".data"
if (port == 27017):
return "/tmp/" + module_name + "_data/" + host + "-" + action + ".data"
else:
return "/tmp/" + module_name + "_data/" + host + "-" + str(port) + "-" + action + ".data"
def ensure_dir(f): def ensure_dir(f):
@ -1381,7 +1600,7 @@ def write_values(file_name, string):
f = None f = None
try: try:
f = open(file_name, 'w') f = open(file_name, 'w')
except IOError, e: except IOError as e:
#try creating #try creating
if (e.errno == 2): if (e.errno == 2):
ensure_dir(file_name) ensure_dir(file_name)
@ -1400,11 +1619,11 @@ def read_values(file_name):
data = f.read() data = f.read()
f.close() f.close()
return 0, data return 0, data
except IOError, e: except IOError as e:
if (e.errno == 2): if (e.errno == 2):
#no previous data #no previous data
return 1, '' return 1, ''
except Exception, e: except Exception as e:
return 2, None return 2, None
@ -1420,8 +1639,8 @@ def calc_delta(old, new):
return 0, delta return 0, delta
def maintain_delta(new_vals, host, action): def maintain_delta(new_vals, host, port, action):
file_name = build_file_name(host, action) file_name = build_file_name(host, port, action)
err, data = read_values(file_name) err, data = read_values(file_name)
old_vals = data.split(';') old_vals = data.split(';')
new_vals = [str(int(time.time()))] + new_vals new_vals = [str(int(time.time()))] + new_vals
@ -1442,8 +1661,8 @@ def replication_get_time_diff(con):
col = 'oplog.$main' col = 'oplog.$main'
firstc = local[col].find().sort("$natural", 1).limit(1) firstc = local[col].find().sort("$natural", 1).limit(1)
lastc = local[col].find().sort("$natural", -1).limit(1) lastc = local[col].find().sort("$natural", -1).limit(1)
first = firstc.next() first = next(firstc)
last = lastc.next() last = next(lastc)
tfirst = first["ts"] tfirst = first["ts"]
tlast = last["ts"] tlast = last["ts"]
delta = tlast.time - tfirst.time delta = tlast.time - tfirst.time

View File

@ -0,0 +1,69 @@
#!/bin/bash
# Check permettant de monitorer une liste de certificats se trouvant dans
# /etc/nagios/ssl_local.cfg
#
# Développé par Will (2022)
#
certs_list_path="/etc/nagios/check_ssl_local_list.cfg"
# Dates in seconds
_10_days="864000"
_15_days="1296000"
critical=0
warning=0
if [[ ! -f "$certs_list_path" ]]; then
touch "$certs_list_path"
fi
certs_list=$(cat "$certs_list_path" | sed -E 's/(.*)#.*/\1/g' | grep -v -E '^$')
for cert_path in $certs_list; do
if [ ! -f "$cert_path" ] && [ ! -d "$cert_path" ]; then
>&2 echo "Warning: path '$cert_path' is not a file or a directory."
warning=1
continue
fi
enddate=$(openssl x509 -noout -enddate -in "$cert_path" | cut -d'=' -f2)
# Check cert expiré (critique)
if ! openssl x509 -checkend 0 -in "$cert_path" &> /dev/null; then
critical=1
>&2 echo "Critical: Cert '$cert_path' has expired on $enddate."
continue
fi
# Check cert expire < 10 jours (critique)
if ! openssl x509 -checkend "$_10_days" -in "$cert_path" &> /dev/null; then
critical=1
>&2 echo "Critical: Cert '$cert_path' will expire on $enddate."
continue
fi
# Check cert expire < 15 jours (warning)
if ! openssl x509 -checkend "$_15_days" -in "$cert_path" &> /dev/null; then
warning=1
>&2 echo "Warning: Cert '$cert_path' will expire on $enddate."
continue
fi
# Cert expire > 15 jours (OK)
echo "Cert '$cert_path' OK."
done
if [ $critical -eq 1 ]; then
exit 2
elif [ $warning -eq 1 ]; then
exit 1
else
exit 0
fi

View File

@ -34,7 +34,7 @@ command[check_pop]=/usr/lib/nagios/plugins/check_pop -H localhost
command[check_pops]=/usr/lib/nagios/plugins/check_pop -S -H localhost -p 995 command[check_pops]=/usr/lib/nagios/plugins/check_pop -S -H localhost -p 995
command[check_ftp]=/usr/lib/nagios/plugins/check_ftp -H localhost command[check_ftp]=/usr/lib/nagios/plugins/check_ftp -H localhost
command[check_http]=/usr/lib/nagios/plugins/check_http -e 301 -I 127.0.0.1 -H localhost command[check_http]=/usr/lib/nagios/plugins/check_http -e 301 -I 127.0.0.1 -H localhost
command[check_https]=/usr/lib/nagios/plugins/check_http -e 403 -I 127.0.0.1 -S -p 443 --sni -H ssl.evolix.net command[check_https]=/usr/lib/nagios/plugins/check_http -e 401,403 -I 127.0.0.1 -S -p 443 --sni -H ssl.evolix.net
command[check_bind]=/usr/lib/nagios/plugins/check_dig -l evolix.net -H localhost command[check_bind]=/usr/lib/nagios/plugins/check_dig -l evolix.net -H localhost
command[check_unbound]=/usr/lib/nagios/plugins/check_dig -l evolix.net -H localhost command[check_unbound]=/usr/lib/nagios/plugins/check_dig -l evolix.net -H localhost
command[check_smb]=/usr/lib/nagios/plugins/check_tcp -H 127.0.0.1 -p 445 command[check_smb]=/usr/lib/nagios/plugins/check_tcp -H 127.0.0.1 -p 445
@ -48,6 +48,7 @@ command[check_redis]=/usr/lib/nagios/plugins/check_tcp -p 6379
command[check_clamd]=/usr/lib/nagios/plugins/check_clamd -H /var/run/clamav/clamd.ctl -v command[check_clamd]=/usr/lib/nagios/plugins/check_clamd -H /var/run/clamav/clamd.ctl -v
command[check_clamav_db]=/usr/lib/nagios/plugins/check_file_age -w 86400 -c 172800 -f /var/lib/clamav/evolix.ndb command[check_clamav_db]=/usr/lib/nagios/plugins/check_file_age -w 86400 -c 172800 -f /var/lib/clamav/evolix.ndb
command[check_ssl]=/usr/lib/nagios/plugins/check_http -f follow -I 127.0.0.1 -S -p 443 -H ssl.evolix.net -C 15,5 command[check_ssl]=/usr/lib/nagios/plugins/check_http -f follow -I 127.0.0.1 -S -p 443 -H ssl.evolix.net -C 15,5
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_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_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 54321

View File

@ -12,6 +12,14 @@
- client - client
- server - server
- name: Create the _openvpn user
user:
name: _openvpn
system: yes
create_home: no
home: "/nonexistent"
shell: "/usr/sbin/nologin"
- name: Create the shellpki user - name: Create the shellpki user
user: user:
name: shellpki name: shellpki
@ -62,7 +70,9 @@
group: shellpki group: shellpki
- name: Generate dhparam - name: Generate dhparam
command: "openssl dhparam -out /etc/shellpki/dh2048.pem 2048" openssl_dhparam:
path: /etc/shellpki/dh2048.pem
size: 2048
- include_role: - include_role:
name: evolix/remount-usr name: evolix/remount-usr
@ -239,7 +249,7 @@
- include_role: - include_role:
name: evolix/remount-usr name: evolix/remount-usr
- name: Copy shellpki script - name: Copy script to check expirations
copy: copy:
src: "shellpki/cert-expirations.sh" src: "shellpki/cert-expirations.sh"
dest: "/usr/share/scripts/cert-expirations.sh" dest: "/usr/share/scripts/cert-expirations.sh"
@ -253,15 +263,43 @@
special_time: monthly 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 VPN {{ ansible_hostname }} : recapitulatif expirations" {{ client_email }}'
- name: Warn the user about command to execute manually - name: Generate the CA password
set_fact:
ca_pwd: "{{ lookup('password', '/dev/null length=25 chars=ascii_letters,digits') }}"
check_mode: no
changed_when: no
- name: Initialization of the CA
shell: 'CA_PASSWORD="{{ ca_pwd }}" shellpki init --non-interactive {{ ansible_fqdn }}'
- name: Creation of the server's certificate
shell: 'CA_PASSWORD="{{ ca_pwd }}" shellpki create --days 3650 --non-interactive {{ ansible_fqdn }}'
- name: Get the server key
shell: 'ls -tr /etc/shellpki/private/ | tail -1'
register: ca_key
check_mode: no
changed_when: no
- name: Configure the server key
replace:
path: /etc/openvpn/server.conf
regexp: 'key /etc/shellpki/private/TO_COMPLETE'
replace: 'key /etc/shellpki/private/{{ ca_key.stdout }}'
- name: Restart OpenVPN
systemd:
name: "openvpn@server.service"
state: restarted
- name: Warn the user about manual checks
pause: pause:
prompt: | prompt: |
/!\ WARNING /!\ /!\ WARNING /!\
You have to manually create the CA on the server with "shellpki init {{ ansible_fqdn }}". The command will ask you to create a password, and will ask you again to give the same one several times. You must check and adjust if necessary the configuration file "/etc/openvpn/server.conf", and then restart the OpenVPN service with "systemctl restart openvpn@server.service".
You have to manually generate the CRL on the server with "openssl ca -gencrl -keyfile /etc/shellpki/cakey.key -cert /etc/shellpki/cacert.pem -out /etc/shellpki/crl.pem -config /etc/shellpki/openssl.cnf". The previously created password will be asked. The "push" parameter may be needed to push a route to the client, so that the client can access that route through OpenVPN.
You have to manually create the server's certificate with "shellpki create {{ ansible_fqdn }}".
You have to adjust the config file "/etc/openvpn/server.conf" for the following parameters : local (to check), cert (to check), key (to add), server (to check), push (to complete if needed). Take note of the generated CA password and store it in your password manager : {{ ca_pwd }}
Finally, you can (re)start the OpenVPN service with "systemctl restart openvpn@server.service".
Press enter to exit when it's done. Press enter to exit when it's done.

View File

@ -56,7 +56,9 @@
group: _shellpki group: _shellpki
- name: Generate dhparam - name: Generate dhparam
command: "openssl dhparam -out /etc/shellpki/dh2048.pem 2048" openssl_dhparam:
path: /etc/shellpki/dh2048.pem
size: 2048
- name: Fix CRL rights in shellpki command - name: Fix CRL rights in shellpki command
lineinfile: lineinfile:
@ -175,7 +177,7 @@
notify: restart nrpe notify: restart nrpe
when: nrpe_evolix_config.stat.exists when: nrpe_evolix_config.stat.exists
- name: Copy shellpki script - name: Copy script to check expirations
copy: copy:
src: "shellpki/cert-expirations.sh" src: "shellpki/cert-expirations.sh"
dest: "/usr/share/scripts/cert-expirations.sh" dest: "/usr/share/scripts/cert-expirations.sh"
@ -189,15 +191,43 @@
special_time: monthly 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 VPN {{ ansible_hostname }} : recapitulatif expirations" {{ client_email }}'
- name: Warn the user about command to execute manually - name: Generate the CA password
set_fact:
ca_pwd: "{{ lookup('password', '/dev/null length=25 chars=ascii_letters,digits') }}"
check_mode: no
changed_when: no
- name: Initialization of the CA
shell: 'CA_PASSWORD="{{ ca_pwd }}" shellpki init --non-interactive {{ ansible_fqdn }}'
- name: Creation of the server's certificate
shell: 'CA_PASSWORD="{{ ca_pwd }}" shellpki create --days 3650 --non-interactive {{ ansible_fqdn }}'
- name: Get the server key
shell: 'ls -tr /etc/shellpki/private/ | tail -1'
register: ca_key
check_mode: no
changed_when: no
- name: Configure the server key
replace:
path: /etc/openvpn/server.conf
regexp: 'key /etc/shellpki/private/TO_COMPLETE'
replace: 'key /etc/shellpki/private/{{ ca_key.stdout }}'
- name: Restart OpenVPN
service:
name: openvpn
state: restarted
- name: Warn the user about manual checks
pause: pause:
prompt: | prompt: |
/!\ WARNING /!\ /!\ WARNING /!\
You have to manually create the CA on the server with "shellpki init {{ ansible_fqdn }}". The command will ask you to create a password, and will ask you again to give the same one several times. You must check and adjust if necessary the configuration file "/etc/openvpn/server.conf", and then restart the OpenVPN service with "rcctl restart openvpn".
You have to manually generate the CRL on the server with "openssl ca -gencrl -keyfile /etc/shellpki/cakey.key -cert /etc/shellpki/cacert.pem -out /etc/shellpki/crl.pem -config /etc/shellpki/openssl.cnf". The previously created password will be asked. The "push" parameter may be needed to push a route to the client, so that the client can access that route through OpenVPN.
You have to manually create the server's certificate with "shellpki create {{ ansible_fqdn }}".
You have to adjust the config file "/etc/openvpn/server.conf" for the following parameters : local (to check), cert (to check), key (to add), server (to check), push (to complete if needed). Take note of the generated CA password and store it in your password manager : {{ ca_pwd }}
Finally, you can (re)start the OpenVPN service with "rcctl restart openvpn".
Press enter to exit when it's done. Press enter to exit when it's done.

View File

@ -1,5 +1,5 @@
user nobody user _openvpn
group nogroup group _openvpn
local {{ ansible_default_ipv4.address }} local {{ ansible_default_ipv4.address }}
port 1194 port 1194

View File

@ -30,6 +30,7 @@
- php-sqlite3 - php-sqlite3
- php-curl - php-curl
- php-ssh2 - php-ssh2
- php-xml
- php-zip - php-zip
- composer - composer
- libphp-phpmailer - libphp-phpmailer

View File

@ -41,5 +41,5 @@ proftpd_accounts:
For generate the sha512 version of yours password : For generate the sha512 version of yours password :
~~~ ~~~
echo "test" | mkpasswd --method=sha-512 - printf "test" | mkpasswd --stdin --method=sha-512
~~~ ~~~

View File

@ -3,12 +3,16 @@ proftpd_hostname: "{{ ansible_hostname }}"
proftpd_fqdn: "{{ ansible_fqdn }}" proftpd_fqdn: "{{ ansible_fqdn }}"
proftpd_default_address: [] proftpd_default_address: []
proftpd_ftp_enable: True proftpd_ftp_enable: True
proftpd_ftp_override: False
proftpd_port: 21 proftpd_port: 21
proftpd_ftps_enable: False proftpd_ftps_enable: False
proftpd_ftps_override: False
proftpd_ftps_port: 990 proftpd_ftps_port: 990
proftpd_ftps_cert: "/etc/ssl/certs/ssl-cert-snakeoil.pem" proftpd_ftps_cert: "/etc/ssl/certs/ssl-cert-snakeoil.pem"
proftpd_ftps_key: "/etc/ssl/private/ssl-cert-snakeoil.key" proftpd_ftps_key: "/etc/ssl/private/ssl-cert-snakeoil.key"
proftpd_sftp_enable: False proftpd_sftp_enable: False
proftpd_sftp_override: False
proftpd_sftp_use_publickeys: False
proftpd_sftp_port: 22222 proftpd_sftp_port: 22222
proftpd_accounts: [] proftpd_accounts: []
proftpd_accounts_final: [] proftpd_accounts_final: []

View File

@ -60,3 +60,18 @@
when: proftpd_sftp_enable | bool when: proftpd_sftp_enable | bool
tags: tags:
- proftpd - proftpd
- name: Allow keys for SFTP account
blockinfile:
dest: "/etc/proftpd/sftp.authorized_keys/{{ item.name }}"
state: present
block: "{{ item.sshkeys }}"
create: yes
mode: 0600
loop: "{{ proftpd_accounts_final }}"
notify: restart proftpd
when:
- proftpd_sftp_enable | bool
- proftpd_sftp_use_publickeys | bool
tags:
- proftpd

View File

@ -20,7 +20,7 @@
src: evolinux.conf.j2 src: evolinux.conf.j2
dest: /etc/proftpd/conf.d/z-evolinux.conf dest: /etc/proftpd/conf.d/z-evolinux.conf
mode: "0644" mode: "0644"
force: no force: "{{ proftpd_ftp_override }}"
notify: restart proftpd notify: restart proftpd
when: proftpd_ftp_enable | bool when: proftpd_ftp_enable | bool
tags: tags:
@ -31,7 +31,7 @@
src: ftps.conf.j2 src: ftps.conf.j2
dest: /etc/proftpd/conf.d/ftps.conf dest: /etc/proftpd/conf.d/ftps.conf
mode: "0644" mode: "0644"
force: no force: "{{ proftpd_ftps_override }}"
notify: restart proftpd notify: restart proftpd
when: proftpd_ftps_enable | bool when: proftpd_ftps_enable | bool
tags: tags:
@ -42,12 +42,26 @@
src: sftp.conf.j2 src: sftp.conf.j2
dest: /etc/proftpd/conf.d/sftp.conf dest: /etc/proftpd/conf.d/sftp.conf
mode: "0644" mode: "0644"
force: no force: "{{ proftpd_sftp_override }}"
notify: restart proftpd notify: restart proftpd
when: proftpd_sftp_enable | bool when: proftpd_sftp_enable | bool
tags: tags:
- proftpd - proftpd
- name: SFTP key folder exists if needed
file:
path: /etc/proftpd/sftp.authorized_keys/
state: directory
mode: "0700"
owner: root
group: root
notify: restart proftpd
when:
- proftpd_sftp_enable | bool
- proftpd_sftp_use_publickeys | bool
tags:
- proftpd
- name: mod_tls_memcache is disabled - name: mod_tls_memcache is disabled
replace: replace:
dest: /etc/proftpd/modules.conf dest: /etc/proftpd/modules.conf

View File

@ -1,5 +1,13 @@
# Evolix's specific configuration # Evolix's specific configuration
{% if proftpd_ftp_override %}
# WARNING : **Probably** ansible managed
{% endif %}
<IfModule !mod_ident.c>
LoadModule mod_ident.c
</IfModule>
ServerName "{{ proftpd_hostname }} FTP Server" ServerName "{{ proftpd_hostname }} FTP Server"
ServerIdent on "FTP Server Ready" ServerIdent on "FTP Server Ready"
AccessGrantMsg "Hey, bienvenue %u sur le serveur FTP {{ proftpd_fqdn }} !" AccessGrantMsg "Hey, bienvenue %u sur le serveur FTP {{ proftpd_fqdn }} !"

View File

@ -1,8 +1,12 @@
{% if proftpd_ftps_override %}
# WARNING : **Probably** ansible managed
{% endif %}
<IfModule !mod_tls.c> <IfModule !mod_tls.c>
LoadModule mod_tls.c LoadModule mod_tls.c
</IfModule> </IfModule>
<VirtualHost 0.0.0.0> <VirtualHost {{ proftpd_default_address | join(' ') }}>
TLSEngine on TLSEngine on
TLSLog /var/log/proftpd/ftps.log TLSLog /var/log/proftpd/ftps.log
TLSProtocol TLSv1 TLSProtocol TLSv1

View File

@ -1,3 +1,7 @@
{% if proftpd_sftp_override %}
# WARNING : **Probably** ansible managed
{% endif %}
<IfModule !mod_tls.c> <IfModule !mod_tls.c>
LoadModule mod_tls.c LoadModule mod_tls.c
</IfModule> </IfModule>
@ -6,15 +10,21 @@
LoadModule mod_sftp.c LoadModule mod_sftp.c
</IfModule> </IfModule>
<VirtualHost 0.0.0.0> <VirtualHost {{ proftpd_default_address | join(' ') }}>
SFTPEngine on SFTPEngine on
Port {{ proftpd_sftp_port }} Port {{ proftpd_sftp_port }}
DefaultRoot ~ DefaultRoot ~
SFTPLog /var/log/proftpd/sftp.log SFTPLog /var/log/proftpd/sftp.log
TransferLog /var/log/proftpd/xferlog TransferLog /var/log/proftpd/xferlog
{% if proftpd_sftp_use_publickeys %}
SFTPAuthMethods publickey password
SFTPAuthorizedUserKeys file:/etc/proftpd/sftp.authorized_keys/%u
{% else %}
SFTPAuthMethods password SFTPAuthMethods password
{% endif %}
SFTPHostKey /etc/ssh/ssh_host_ecdsa_key SFTPHostKey /etc/ssh/ssh_host_ecdsa_key
SFTPHostKey /etc/ssh/ssh_host_rsa_key SFTPHostKey /etc/ssh/ssh_host_rsa_key

View File

@ -0,0 +1,226 @@
#!/usr/bin/env python3
from optparse import OptionParser
import shlex
import subprocess
import sys
import requests
import json
if "check_output" not in dir( subprocess ): # duck punch it in!
def f(*popenargs, **kwargs):
if 'stdout' in kwargs:
raise ValueError('stdout argument not allowed, it will be overridden.')
process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
output, unused_err = process.communicate()
retcode = process.poll()
if retcode:
cmd = kwargs.get("args")
if cmd is None:
cmd = popenargs[0]
raise subprocess.CalledProcessError(retcode, cmd)
return output
subprocess.check_output = f
class RabbitCmdWrapper(object):
"""So basically this just runs rabbitmqctl commands and returns parsed output.
Typically this means you need root privs for this to work.
Made this it's own class so it could be used in other monitoring tools
if desired."""
@classmethod
def list_connections(cls):
args = shlex.split("sudo rabbitmqctl list_connections")
cmd_result = subprocess.check_output(args, text=True).strip()
results = cls._parse_list_results(cmd_result)
return results
@classmethod
def list_queues(cls):
args = shlex.split('sudo rabbitmqctl list_queues')
cmd_result = subprocess.check_output(args, text=True).strip()
results = cls._parse_list_results(cmd_result)
return results
@classmethod
def status(cls):
args = shlex.split('sudo rabbitmqctl status')
cmd_result = subprocess.check_output(args, text=True).strip()
results = cls._parse_list_results(cmd_result)
return results
@classmethod
def _parse_list_results(cls, result_string):
results = result_string.strip().split('\n')
#remove text fluff
if "Listing connections ..." in results: results.remove("Listing connections ...")
if "Listing queues ..." in results: results.remove("Listing queues ...")
return_data = []
for row in results:
return_data.append(row.split('\t'))
return return_data
def check_connection_count(critical=0, warning=0):
"""Checks to make sure the numbers of connections are within parameters."""
try:
count = len(RabbitCmdWrapper.list_connections())
if count >= critical:
print("CRITICAL - Connection Count %d" % count)
sys.exit(2)
elif count >= warning:
print("WARNING - Connection Count %d" % count)
sys.exit(1)
else:
print("OK - Connection Count %d" % count)
except Exception as err:
print("CRITICAL - %s" % err)
def check_queues_count(critical=1000, warning=1000):
"""
A blanket check to make sure all queues are within count parameters.
TODO: Possibly break this out so test can be done on individual queues.
"""
try:
critical_q = []
warning_q = []
results = RabbitCmdWrapper.list_queues()
for queue in results:
if queue.count == 2:
count = int(queue[1])
if count >= critical:
critical_q.append("%s: %s" % (queue[0], count))
elif count >= warning:
warning_q.append("%s: %s" % (queue[0], count))
if critical_q:
print("CRITICAL - %s" % ", ".join(critical_q))
sys.exit(2)
elif warning_q:
print("WARNING - %s" % ", ".join(warning_q))
sys.exit(1)
else:
print("OK - NO QUEUES EXCEED THRESHOLDS")
sys.exit(0)
except Exception as err:
print("CRITICAL - %s" % err)
sys.exit(2)
def check_mem_usage(critical=75, warning=50):
"""Check to make sure the RAM usage of rabbitmq process does not exceed 50%% of its max"""
try:
results = RabbitCmdWrapper.status()
for idx,val in enumerate(results):
if "memory," in str(val):
mem_used_raw = str(results[idx + 1])
if "vm_memory_limit" in str(val):
mem_limit_raw = str(val)
memory_used = float(filter(str.isdigit, mem_used_raw))
memory_limit = float(filter(str.isdigit, mem_limit_raw))
percent_usage = int(memory_used/memory_limit * 100)
if percent_usage > critical:
print("CRITICAL - RABBITMQ RAM USAGE at %s%% of max" % percent_usage)
sys.exit(2)
elif percent_usage > warning:
print("WARNING - RABBITMQ RAM USAGE at %s%% of max" % percent_usage)
sys.exit(1)
else:
print("OK - RABBITMQ RAM USAGE OK at %s%% of max" % percent_usage)
sys.exit(0)
except Exception as err:
print("Critical - %s" % err)
sys.exit(2)
def check_aliveness(username, password, timeout, cluster):
"""Declares a test queue, then publishes and consumes a message. Intended for use by monitoring tools. If everything is working correctly, will return HTTP status 200 with body"""
try:
r = requests.get("http://%s:15672/api/aliveness-test/%%2F" % cluster, auth=(username, password), timeout=timeout)
except requests.exceptions.RequestException as e: # Throw error if rabbitmq is down
print("Critical - %s" % e)
sys.exit(2)
if r.status_code == 200:
print("OK - RABBITMQ Aliveness Test Returns: %s" % r)
sys.exit(0)
elif r.status_code != 200:
print("CRITICAL - RabbitMQ Error: %s" % r.content)
sys.exit(2)
else:
print("UNKNOWN - RABBITMQ Aliveness Test")
sys.ext(1)
def check_cluster(username, password, timeout, cluster):
"""Checks the health of a cluster, if a node is not running mark as offline """
try:
url = "http://%s:15672/api/nodes" % cluster
r = requests.get(url, auth=(username, password), timeout=timeout)
except requests.exceptions.RequestException as e: # Throw error if no response
print("Critical - %s" % e)
sys.exit(2)
text = r.text
nodes = json.loads(text)
running_nodes = []
failed_nodes = []
for node in nodes:
if not node['running']:
failed_nodes.append(node['name'])
if node['running']:
running_nodes.append(node['name'])
if len(failed_nodes) == 1:
print("WARNING: RabbitMQ cluster is degraged: Not running %s" % failed_nodes[0])
sys.exit(1)
elif len(failed_nodes) >= 2:
print("CRITICAL: RabbitMQ cluster is critical: Not running %s" % failed_nodes)
sys.exit(2)
else:
print("OK: RabbitMQ cluster members: %s" % (" ".join(running_nodes)))
sys.exit(0)
USAGE = """Usage: ./check_rabbitmq -a [action] -C [critical] -W [warning]
Actions:
- connection_count
checks the number of connection in rabbitmq's list_connections
- queues_count
checks the count in each of the queues in rabbitmq's list_queues
- mem_usage
checks to ensure mem usage of rabbitmq process does not exceed 50%
- aliveness
Use the /api/aliveness-test API to send/receive a message. (requires -u username -p password args)
- cluster_status
Parse /api/nodes to check the cluster status. (requires -u username -p password"""
if __name__ == "__main__":
parser = OptionParser(USAGE)
parser.add_option("-a", "--action", dest="action",
help="Action to Check")
parser.add_option("-C", "--critical", dest="critical",
type="int", help="Critical Threshold")
parser.add_option("-W", "--warning", dest="warning",
type="int", help="Warning Threshold")
parser.add_option("-u", "--username", dest="username", default="guest",
type="string", help="RabbitMQ username, Default guest")
parser.add_option("-p", "--password", dest="password", default="guest",
type="string", help="RabbitMQ password, Default guest")
parser.add_option("-t", "--timeout", dest="timeout", default=1,
type="int", help="Request Timeout, defaults to 1 second")
parser.add_option("-c", "--cluster", dest="cluster", default="localhost",
type="string", help="Cluster IP/DNS name, defaults to localhost")
(options, args) = parser.parse_args()
if options.action == "connection_count":
check_connection_count(options.critical, options.warning)
elif options.action == "queues_count":
check_queues_count(options.critical, options.warning)
elif options.action == "mem_usage":
check_mem_usage(options.critical, options.warning)
elif options.action == "aliveness":
check_aliveness(options.username, options.password, options.timeout, options.cluster)
elif options.action == "cluster_status":
check_cluster(options.username, options.password, options.timeout, options.cluster)
else:
print("Invalid action: %s" % options.action)
print(USAGE)

View File

@ -24,6 +24,17 @@
group: root group: root
mode: "0755" mode: "0755"
force: yes force: yes
when: ansible_distribution_major_version is version('11', '<=')
- name: check_rabbitmq (Python 3 version) is installed
copy:
src: check_rabbitmq.python3
dest: /usr/local/lib/nagios/plugins/check_rabbitmq
owner: root
group: root
mode: "0755"
force: yes
when: ansible_distribution_major_version is version('11', '==')
- name: check_rabbitmq is available for NRPE - name: check_rabbitmq is available for NRPE
lineinfile: lineinfile:

View File

@ -11,6 +11,15 @@
tags: tags:
- redis - redis
- name: Config directory permissions are set
file:
dest: "{{ redis_conf_dir }}"
mode: "0750"
owner: redis
group: redis
tags:
- redis
- name: Redis is running and enabled on boot. - name: Redis is running and enabled on boot.
systemd: systemd:
name: "{{ redis_systemd_name }}" name: "{{ redis_systemd_name }}"

View File

@ -28,9 +28,9 @@
- name: "Instance '{{ redis_instance_name }}' config directory is present" - name: "Instance '{{ redis_instance_name }}' config directory is present"
file: file:
dest: "{{ redis_conf_dir }}" dest: "{{ redis_conf_dir }}"
mode: "0755" mode: "0750"
owner: "root" owner: "redis-{{ redis_instance_name }}"
group: "root" group: "redis-{{ redis_instance_name }}"
follow: yes follow: yes
state: directory state: directory
tags: tags:
@ -39,9 +39,9 @@
- name: "Instance '{{ redis_instance_name }}' config hooks directories are present" - name: "Instance '{{ redis_instance_name }}' config hooks directories are present"
file: file:
dest: "{{ _dir }}" dest: "{{ _dir }}"
mode: "0755" mode: "0750"
owner: "root" owner: "redis-{{ redis_instance_name }}"
group: "root" group: "redis-{{ redis_instance_name }}"
follow: yes follow: yes
state: directory state: directory
loop: loop:

View File

@ -2,6 +2,6 @@
[Service] [Service]
ExecStart= ExecStart=
ExecStart=/usr/sbin/varnishd -F -j {{ varnish_jail }} {{ varnish_addresses | map('regex_replace', '^(.*)$', '-a \\1') | list | join(' ') }} -T {{ varnish_management_address }} -f {{ varnish_config_file }} -S {{ varnish_secret_file }} -s {{ varnish_storage }} -p thread_pools={{ varnish_thread_pools }} -p thread_pool_add_delay={{ varnish_thread_pool_add_delay }} -p thread_pool_min={{ varnish_thread_pool_min }} -p thread_pool_max={{ varnish_thread_pool_max }} ExecStart=/usr/sbin/varnishd -j {{ varnish_jail }} -F {{ varnish_addresses | map('regex_replace', '^(.*)$', '-a \\1') | list | join(' ') }} -T {{ varnish_management_address }} -f {{ varnish_config_file }} -S {{ varnish_secret_file }} -s {{ varnish_storage }} -p thread_pools={{ varnish_thread_pools }} -p thread_pool_add_delay={{ varnish_thread_pool_add_delay }} -p thread_pool_min={{ varnish_thread_pool_min }} -p thread_pool_max={{ varnish_thread_pool_max }}
ExecReload= ExecReload=
ExecReload=/etc/varnish/reload-vcl.sh ExecReload=/etc/varnish/reload-vcl.sh

13
vrrpd/defaults/main.yml Normal file
View File

@ -0,0 +1,13 @@
---
vrrp_addresses: []
# - {
# interface: Null # the interface name to run on
# delay: 10 # the advertisement interval (in sec) (default: 1)
# id: Null # the id of the virtual server [1-255]
# priority: Null # the priority of this host in the virtual server (default: 100)
# authentication: Null # authentification type: auth=(none|pw/hexkey|ah/hexkey) hexkey=0x[0-9a-fA-F]+
# label: Null # use this name is syslog messages (helps when several vrid are running)
# ip: Null # the ip address(es) (and optionnaly subnet mask) of the virtual server
# state: Null # 'started' or 'stopped'
# }

20
vrrpd/tasks/ip.yml Normal file
View File

@ -0,0 +1,20 @@
---
- name: set unit name
set_fact:
vrrp_systemd_unit_name: "vrrp-{{ vrrp_address.id }}.service"
- name: add systemd unit
template:
src: vrrp.service.j2
dest: "/etc/systemd/system/{{ vrrp_systemd_unit_name }}"
force: yes
register: vrrp_systemd_unit
- name: enable and start systemd unit
systemd:
name: "{{ vrrp_systemd_unit_name }}"
daemon_reload: yes
enabled: yes
state: "{{ vrrp_address.state }}"
when: vrrp_systemd_unit is changed

View File

@ -14,7 +14,36 @@
tags: tags:
- vrrpd - vrrpd
- name: Adjust sysctl config - name: Adjust sysctl config (except rp_filter)
sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
sysctl_file: /etc/sysctl.d/vrrpd.conf
sysctl_set: yes
state: present
loop:
- { name: 'net.ipv4.conf.all.arp_ignore', value: 1 }
- { name: 'net.ipv4.conf.all.arp_announce', value: 2 }
- { name: 'net.ipv4.ip_nonlocal_bind', value: 1 }
tags:
- vrrpd
- name: look if rp_filter is managed by minifirewall
command: grep "SYSCTL_RP_FILTER=" /etc/default/minifirewall
failed_when: False
changed_when: False
check_mode: no
register: grep_sysctl_rp_filter_minifirewall
- name: Configure SYSCTL_RP_FILTER in minifirewall
lineinfile:
dest: "/etc/default/minifirewall"
line: "SYSCTL_RP_FILTER='0'"
regexp: "SYSCTL_RP_FILTER=('|\").*('|\")"
create: no
when: grep_sysctl_rp_filter_minifirewall.rc == 0
- name: Adjust sysctl config (only rp_filter)
sysctl: sysctl:
name: "{{ item.name }}" name: "{{ item.name }}"
value: "{{ item.value }}" value: "{{ item.value }}"
@ -23,10 +52,13 @@
state: present state: present
loop: loop:
- { name: 'net.ipv4.conf.default.rp_filter', value: 0 } - { name: 'net.ipv4.conf.default.rp_filter', value: 0 }
- { name: 'net.ipv4.conf.eth0.rp_filter', value: 0 }
- { name: 'net.ipv4.conf.all.rp_filter', value: 0 } - { name: 'net.ipv4.conf.all.rp_filter', value: 0 }
- { name: 'net.ipv4.conf.all.arp_ignore', value: 1 } when: grep_sysctl_rp_filter_minifirewall.rc != 0
- { name: 'net.ipv4.conf.all.arp_announce', value: 2 }
- { name: 'net.ipv4.ip_nonlocal_bind', value: 1 }
tags: tags:
- vrrpd - vrrpd
- name: Create VRRP address
include: ip.yml
loop: "{{ vrrp_addresses }}"
loop_control:
loop_var: "vrrp_address"

View File

@ -0,0 +1,15 @@
[Unit]
Description=VRRP Daemon for IP {{ vrrp_address.ip }} on {{ vrrp_address.interface }}
After=network.target
[Service]
ExecStart=/usr/sbin/vrrpd -i {{ vrrp_address.interface | mandatory }} -x -D -d {{ vrrp_address.delay | mandatory }} -v {{ vrrp_address.id | mandatory }} -p {{ vrrp_address.priority | mandatory }} -a {{ vrrp_address.authentication | mandatory }} -l {{ vrrp_address.label | mandatory }} {{ vrrp_address.ip | mandatory }}
# PIDFile=/var/run/vrrpd_{{ vrrp_address.label }}_{{ vrrp_address.id }}.pid
Restart=on-failure
Type=forking
IgnoreSIGPIPE=no
KillMode=process
RemainAfterExit=yes
[Install]
WantedBy=default.target

View File

@ -1,7 +1,6 @@
--- ---
nextcloud_webserver: 'nginx' nextcloud_version: "latest-24"
nextcloud_version: "21.0.0" nextcloud_archive_name: "{{ nextcloud_version }}.tar.bz2"
nextcloud_archive_name: "nextcloud-{{ nextcloud_version }}.tar.bz2"
nextcloud_releases_baseurl: "https://download.nextcloud.com/server/releases/" nextcloud_releases_baseurl: "https://download.nextcloud.com/server/releases/"
nextcloud_instance_name: "nextcloud" nextcloud_instance_name: "nextcloud"

View File

@ -8,3 +8,8 @@
service: service:
name: nginx name: nginx
state: reloaded state: reloaded
- name: reload apache
service:
name: apache2
state: reloaded

View File

@ -1,4 +1 @@
--- ---
# dependencies:
# - { role: nginx, when: nextcloud_webserver == 'nginx' }
# - { role: php, php_fpm_enable: True }

View File

@ -0,0 +1,33 @@
---
- name: "Get PHP Version"
shell: 'php -v | grep "PHP [0-9]." | sed -E "s/PHP ([0-9]\.[0-9]).*/\1/g;"'
register: shell_php
check_mode: no
- name: "Set variables"
set_fact:
php_version: "{{ shell_php.stdout }}"
- name: Apply specific PHP settings (apache)
ini_file:
path: "/etc/php/{{ php_version }}/apache2/conf.d/zzz-evolinux-custom.ini"
section: ''
option: "{{ item.option }}"
value: "{{ item.value }}"
notify: reload apache
with_items:
- {option: 'allow_url_fopen', value: 'On'}
- {option: 'disable_functions', value: ''}
- {option: 'max_execution_time', value: '300'}
- {option: 'memory_limit', value: '512M'}
- name: Apply specific PHP settings (cli)
ini_file:
path: "/etc/php/{{ php_version }}/cli/conf.d/zzz-evolinux-custom.ini"
section: ''
option: "{{ item.option }}"
value: "{{ item.value }}"
with_items:
- {option: 'allow_url_fopen', value: 'On'}
- {option: 'apc.enable_cli', value: 'On'}

View File

@ -0,0 +1,23 @@
---
- name: Copy Apache vhost
template:
src: apache-vhost.conf.j2
dest: "/etc/apache2/sites-available/{{ nextcloud_instance_name }}.conf"
mode: "0640"
notify: reload apache
tags:
- nextcloud
- name: Enable Apache vhost
file:
src: "/etc/apache2/sites-available/{{ nextcloud_instance_name }}.conf"
dest: "/etc/apache2/sites-enabled/{{ nextcloud_instance_name }}.conf"
state: link
notify: reload apache
tags:
- nextcloud
# - name: Generate ssl config
# shell:
# cmd: "/usr/local/sbin/vhost-domains {{ nextcloud_instance_name }} | /usr/local/sbin/make-csr {{ nextcloud_instance_name }}"
# creates: "/etc/nginx/ssl/{{ nextcloud_instance_name }}.conf"

View File

@ -16,10 +16,12 @@
- php-apcu - php-apcu
- php-redis - php-redis
- php-bcmath - php-bcmath
- php-imagick
- libmagickcore-6.q16-6-extra
tags: tags:
- nextcloud - nextcloud
# dependency for mysql_user and mysql_db # dependency for mysql_user and mysql_db - python2
- name: python modules is installed (Ansible dependency) - name: python modules is installed (Ansible dependency)
apt: apt:
name: name:
@ -30,7 +32,7 @@
- nextcloud - nextcloud
when: ansible_python_version is version('3', '<') when: ansible_python_version is version('3', '<')
# dependency for mysql_user and mysql_db # dependency for mysql_user and mysql_db - python3
- name: python3 modules is installed (Ansible dependency) - name: python3 modules is installed (Ansible dependency)
apt: apt:
name: name:
@ -41,12 +43,14 @@
- nextcloud - nextcloud
when: ansible_python_version is version('3', '>=') when: ansible_python_version is version('3', '>=')
- include: apache-system.yml
- include: user.yml - include: user.yml
- include: archive.yml - include: archive.yml
- include: vhost.yml - include: apache-vhost.yml
- include: mysql.yml - include: mysql-user.yml
- include: config.yml - include: config.yml

View File

@ -1,15 +1,15 @@
--- ---
- name: Create Nextcloud group - name: Create {{ nextcloud_user }} unix group
group: group:
name: "{{ nextcloud_instance_name | mandatory }}" name: "{{ nextcloud_user | mandatory }}"
state: present state: present
tags: tags:
- nextcloud - nextcloud
- name: Create Nextcloud user - name: Create {{ nextcloud_user | mandatory }} unix user
user: user:
name: "{{ nextcloud_user | mandatory }}" name: "{{ nextcloud_user | mandatory }}"
group: "{{ nextcloud_user }}" group: "{{ nextcloud_user | mandatory }}"
home: "{{ nextcloud_home | mandatory }}" home: "{{ nextcloud_home | mandatory }}"
shell: '/bin/bash' shell: '/bin/bash'
create_home: True create_home: True
@ -18,17 +18,11 @@
tags: tags:
- nextcloud - nextcloud
- name: Add the user 'www-data' to Nextcloud group
user:
name: www-data
groups: "{{ nextcloud_user | mandatory }}"
append: yes
- name: Create top-level directories - name: Create top-level directories
file: file:
dest: "{{ item }}" dest: "{{ item }}"
state: directory state: directory
mode: "0770" mode: "0700"
owner: "{{ nextcloud_user }}" owner: "{{ nextcloud_user }}"
group: "{{ nextcloud_user }}" group: "{{ nextcloud_user }}"
loop: loop:

View File

@ -1,34 +0,0 @@
---
- block:
- name: Copy Nginx vhost
template:
src: nginx.conf.j2
dest: "/etc/nginx/sites-available/{{ nextcloud_instance_name }}.conf"
mode: "0640"
notify: reload nginx
tags:
- nextcloud
- name: Enable Nginx vhost
file:
src: "/etc/nginx/sites-available/{{ nextcloud_instance_name }}.conf"
dest: "/etc/nginx/sites-enabled/{{ nextcloud_instance_name }}.conf"
state: link
notify: reload nginx
tags:
- nextcloud
- name: Generate ssl config
shell:
cmd: "/usr/local/sbin/vhost-domains {{ nextcloud_instance_name }} | /usr/local/sbin/make-csr {{ nextcloud_instance_name }}"
creates: "/etc/nginx/ssl/{{ nextcloud_instance_name }}.conf"
- name: Copy PHP-FPM pool
template:
src: php-fpm.conf.j2
dest: "/etc/php/7.3/fpm/pool.d/{{ nextcloud_instance_name }}.conf"
mode: "0640"
notify: reload php-fpm
tags:
- nextcloud
when: nextcloud_webserver == 'nginx'

View File

@ -0,0 +1,41 @@
<VirtualHost *:80 *:443>
ServerName {{ nextcloud_domains[0] }}
{% for domain_alias in nextcloud_domains[1:] %}
ServerAlias {{ domain_alias }}
{% endfor %}
# SSLEngine on
# SSLCertificateFile /etc/letsencrypt/live/{{ nextcloud_instance_name }}/fullchain.pem
# SSLCertificateKeyFile /etc/letsencrypt/live/{{ nextcloud_instance_name }}/privkey.pem
DocumentRoot {{ nextcloud_webroot }}/
<Directory {{ nextcloud_webroot }}/>
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
<IfModule mod_dav.c>
Dav off
</IfModule>
</Directory>
# SSL Redirect
# RewriteEngine On
# RewriteCond %{HTTPS} !=on
# RewriteCond %{HTTP:X-Forwarded-Proto} !=https
# RewriteRule ^ https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]
# ITK
AssignUserID {{ nextcloud_user }} {{ nextcloud_user }}
# LOG
CustomLog /var/log/apache2/access.log vhost_combined
ErrorLog /var/log/apache2/error.log
# PHP
php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f {{ nextcloud_user }}"
php_admin_value open_basedir "/usr/share/php:{{ nextcloud_home }}:/tmp"
</VirtualHost>

View File

@ -1,134 +0,0 @@
upstream php-handler-{{ nextcloud_instance_name }} {
server unix:/var/run/php/php-fpm-{{ nextcloud_instance_name }}.sock;
}
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ nextcloud_domains | join(' ') }};
access_log {{ nextcloud_home }}/log/access.log;
error_log {{ nextcloud_home }}/log/error.log;
include /etc/nginx/snippets/letsencrypt.conf;
include /etc/nginx/ssl/{{ nextcloud_instance_name }}.conf;
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always;
add_header X-XSS-Protection "1; mode=block" always;
# Remove X-Powered-By, which is an information leak
fastcgi_hide_header X-Powered-By;
root {{ nextcloud_webroot }};
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Make a regex exception for `/.well-known` so that clients can still
# access it despite the existence of the regex rule
# `location ~ /(\.|autotest|...)` which would otherwise handle requests
# for `/.well-known`.
location ^~ /.well-known {
# The following 6 rules are borrowed from `.htaccess`
location = /.well-known/carddav { return 301 /remote.php/dav/; }
location = /.well-known/caldav { return 301 /remote.php/dav/; }
# Anything else is dynamically handled by Nextcloud
location ^~ /.well-known { return 301 /index.php$uri; }
location ~ ^/.well-known/acme-challenge/* { allow all; }
try_files $uri $uri/ =404;
}
# set max upload size
client_max_body_size 512M;
fastcgi_buffers 64 4K;
# Enable gzip but do not remove ETag headers
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
location / {
rewrite ^ /index.php;
}
location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
deny all;
}
location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
deny all;
}
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy)\.php(?:$|\/) {
fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
set $path_info $fastcgi_path_info;
try_files $fastcgi_script_name =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_param HTTPS on;
# Avoid sending the security headers twice
fastcgi_param modHeadersAvailable true;
# Enable pretty urls
fastcgi_param front_controller_active true;
fastcgi_pass php-handler-{{ nextcloud_instance_name }};
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
}
location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
try_files $uri/ =404;
index index.php;
}
# Adding the cache control header for js, css and map files
# Make sure it is BELOW the PHP block
location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463";
# Add headers to serve security related headers (It is intended to
# have those duplicated to the ones above)
# Before enabling Strict-Transport-Security headers please read into
# this topic first.
#add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
#
# WARNING: Only add the preload option once you read about
# the consequences in https://hstspreload.org/. This option
# will add the domain to a hardcoded list that is shipped
# in all major browsers and getting removed from this list
# could take several months.
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always;
add_header X-XSS-Protection "1; mode=block" always;
# Optional: Don't log access to assets
access_log off;
}
location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$ {
try_files $uri /index.php$request_uri;
# Optional: Don't log access to other assets
access_log off;
}
}

View File

@ -1,17 +0,0 @@
[{{ nextcloud_instance_name }}]
user = {{ nextcloud_user }}
group = {{ nextcloud_user }}
listen = /run/php/php-fpm-{{ nextcloud_instance_name }}.sock
listen.owner = {{ nextcloud_user }}
listen.group = {{ nextcloud_user }}
pm = ondemand
pm.max_children = 50
pm.process_idle_timeout = 120s
pm.status_path = /fpm_status
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = {{ nextcloud_home }}/tmp
env[TMPDIR] = {{ nextcloud_home }}/tmp
env[TEMP] = {{ nextcloud_home }}/tmp