check_by_ssh_wrapper

En essayant de mutualiser au maximum la configuration des services Nagios (ou Shinken dans mon cas) et la configuration NRPE des machines supervisées, il arrive parfois qu’une vérification renvoie trop de données pour NRPE ou qu’on doive accéder à une machine en DMZ voir externe dont on ne peut pas laisser le port NRPE ouvert.

Sur un des parcs que je supervise, alors que mes configurations NRPE permettent de vérifier (entre autre) l’espace disque disponible sur tous les systèmes de fichiers locaux, je me suis retrouvé avec un NAS en DMZ contenant de nombreux systèmes de fichiers (un volume LVM par partage). Le volume de données renvoyé, avec les données de performances dépassait la taille acceptée par NRPE (1 ko de mémoire). Plutôt que de déporter la ligne de commande NRPE vers la configuration Shinken et me retrouver à devoir gérer les problèmes d’échapements, de droits et ainsi complexifier ma conf Shinken, j’ai écrit ce petit script qui prend via check_by_ssh les mêmes paramètres que check_nrpe et lit la configuration NRPe sur le client afin de valider la commande et l’exécuter.

Le code

Il s’agit d’un simple script en bash, aujourd’hui hébergé sur GitHub. Au moment où j’écris ce billet, le code est le suivant :

#!/bin/bash
#
# check_by_ssh_wrapper
#
# This script provides access to commands declared in nrpe to check_by_ssh
# Please set the nrpeconf variable to the right value
# You must generate a ssh key on the nagios server, copy it in .ssh/authorized_keys
# in nagios (or nrpe) user home directory on distant server, then add this at
# the begining of the line juste before the key:
# no-pty,no-port-forwarding,command="/usr/local/bin/check_by_ssh_wrapper $SSH_ORIGINAL_COMMAND"
#
# You can the use $USER1$/check_by_ssh -H <distant host> -l nagios -C 'check_cmd [args]'
#
# Freely inspired by nagios_ssh_framework. Can be used when nrpe port can't be accessed
# or check_command returns to many text for nrpe and you want to keep facilities of nrpe
# config files.
#
# Changes an Modifications:
# 2011-10-12 - Landry MINOZA - V 1.0
# Created because check_disks returns to many lines for nrpe with one of my servers
#
# Copyright: Telbase Formation Conseil, MUSEE D'ORSAY 2011
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Set main nrpe.cfg file
nrpeconf=/etc/nagios/nrpe.cfg

# Get cmdname
cmdname=$1
if [ -z "$cmdname" ] ; then
        echo "WARNING, no command name provided"
        exit 1
fi
shift
# Get optionnal args
cmdargs=$@

# Declare an array of commands
declare -A command

# find all nrpe conf files
include=$(sed -ne '/^include=/ s/^.*=// p' $nrpeconf)
include_dir=$(sed -ne '/^include_dir=/ s/^.*=// p' $nrpeconf)

# Parse all nrpe conf files for command[*]= arguments
for cfgfile in $(echo -e "$nrpeconf\n${include}\n${include_dir}*.cfg") ;do
        eval $(sed -ne '/^command\[/ s/=\(.*\)$/="\1"/ p' $cfgfile)
done

# Check if command[$cmdname] exists
if [ -z "${command[$cmdname]}" ] ; then
        echo "WARNING, command $cmdname does not exist"
        exit 1
fi

# Launch check
exec ${command[$cmdname]} $cmdargs
exit

Le code peut être difisé en 8 parties :

  • Ligne 38, à éditer, il s’agit de l’emplacement de la configuration NRPE (ici pour une Debian stable).
  • Ligne 40 à 48, récupération et vérification des paramètres.
  • Ligne 51, déclaration explicite (obligatoire) d’un tableau associatif de commandes, il servira à stocker pour chaque commande nommée de la configuration NRPe la ligne de commande correspondante.
  • Ligne 54 et 55, récupération des directives include et include_dir du fichier nrpe.conf afin de référencer ces fichiers inclus. Attention, cette recherche des fichiers inclus n’est pas récursive, seule les inclusions déclarées dans le fichier de configuration principal seront prises en compte.
  • Ligne 58 et 60, on boucle sur la liste des fichiers trouvés.
  • Ligne 59, cette ligne est un peu le cœur du script, c’est une astuce s’appuyant sur la forme des paramètres NRPE, en effet, vu que pour déclarer une commande NRPE on écrit : command[nom_commande]=ligne_commande params il suffit d’extraire ces lignes et d’entourer la ligne de commande (après le "=") de guillements puis de les exécuter via eval pour nourrir notre tableau associatif command déclaré plus haut.
  • Ligne 63, on teste s’il esxite un commande avec le nom passé en paramètre à notre script.
  • Enfin ligne 69, on exécute la commande spécifiée avec ses paramètres. Le exit explicite à la fin permet de s’assurer que l’état de sortie soit le même que celui de la commande donc que celui-ci soit bien transmis à Nagios.

Installation

Ce script s’installe sur la machine supervisée, pas sur le serveur de supervision, par exemple dans /usr/local/bin. L’utilisateur exécutant le démon NRPE (sur Debian, il s’agit de l’utilisateur nagios) doit avoir les droits d’exécution sur le script. Par défaut, cet utilisateur n’a pas de mot de passe, et on ne souhaite pas lui en affecter un. De toute façon, ce n’est jamais une bonne idée d’avoir des mots de passes dans la configuration Nagios. Il faut commencer par créer une clé SSH sur le serveur de supervision en utilisant la commande ssh_keygen sous l’identité de l’utilisateur exécutant le serveur de supervision. Par défaut, cette commande va générer une clé rsa, la placer dans $HOME/.ssh/id_rsa et placer la clé publique dans $HOME/.ssh/id_rsa.pub. C’est cette dernière qui nous intéresse.

Il faut créer dans le $HOME de l’utilisateur exécutant le démon NRPE (/var/lib/nagios sur Debian) un répertoire .ssh avec les droits unix rwx------

mkdir /var/lib/nagios/.ssh
chown nagios:nagios /var/lib/nagios/.ssh
chmod u=rwx,go= /var/lib/nagios/.ssh

Dans ce répertoire on place un fichier nommé authorized_keys ne contenant que la ligne suivante :

no-pty,no-port-forwarding,command="/usr/local/bin/check_by_ssh_wrapper $SSH_ORIGINAL_COMMAND" ssh-rsa AAAA… user@server

Remplacer AAAA… user@server par le contenu du fichier id_rsa.pub du serveur de supervision. Cette ligne [1] permet de n’autoriser à l’utilisateur se connectant avec cette clé publique que la lancement de la commande check_by_ssh_wrapper (il est plus que conseillé de mettre un chemin absolu) en interdisant les transferts de ports et l’allocation d’un pseudo terminal. La commande originellement passé à ssh sera fournie en argument à notre script via la variable $SSH_ORIGINAL_COMMAND.

Utilisation

Dans la configuration Nagios, il ne reste plus qu’a créer une commande :

define command{
        command_name check_by_ssh
        command_line $USER1$/check_by_ssh -H $HOSTADDRESS$ -t 60 -l nagios -C '$ARG1$ $ARG2$'
}

Celle-ci pourra ensuite être utilisée de la même façon que le check_nrpe dans les services :

define service{
        use                     base-service
        service_description     check_disks
        display_name            Check Disks
        check_command           check_by_ssh!check_disks
}

Conclusion

Ce script n’est sans doute pas parfait, je me suis par exemple rendu compte en rédigeant ce billet qu’il ne gère pas les inclusions récursives, mais il fonctionne parfaitement depuis 2 ans, et m’a permis de simplifier grandement l’utilisation du plugin check_by_ssh tout en le sécurisant puisque seules les commandes déclarées dans la configuration nrpe sont exécutables.

[1] Un article complet sur ssh (et PuTTY) est en préparation

Commentaires

Comments powered by Disqus