Fin.

Un poco triste y melancólico escribo unas palabras para despedirme del blog.

El registro del dominio se remonta a 2008, cuando empecé mis primeras entradas utilizando DotClear como gestor de contenido. Luego de algunos problemas de hosting, que siempre fue cedido gratuitamente por mi gran amigo DAX, volví a la carga utilizando WordPress y migrando la mayor parte de los artículos vigentes.
El sitio tuvo sus altas y bajas, pero siempre hice de el, lo que creí mejor. Todo el contenido o casi todo fue de mi autoría y aunque algo escaso, pocos blogs sobre software libre pueden presumir de generar contenido propios y originales.

Agradezco a DAX el haberme dado este espacio, a las personas que comentaron las entradas y a aquellos que enlazaron artículos.

No se cuanto tiempo más estará en línea el blog, quizás un mes, quizás hasta fin de año.

Bye!”

Script para definir contacto temporal de Icinga o Nagios.

Hoy les traigo un pequeño script escrito en Bash para definir contactos temporales de Icinga o Nagios. Para quienes no estén familiarizados con Icinga, he aquí un pequeño extracto de su web:

Icinga es un sistema de control, de calidad empresarial y de código abierto, que vigila a través de la red y a cualquier recurso de red imaginable, informa al usuario de los errores y las recuperaciones y genera datos de rendimiento de informes. Escalable y extensible, Icinga puede monitorear ambientes grandes y complejos en ubicaciones dispersas. Icinga es un fork de Nagios y es compatible con versiones anteriores. Así, las configuraciones de Nagios, plugins y addons se pueden usar con Icinga. Aunque Icinga conserva todas las características existentes de su predecesor, y se basa en ellas para añadir muchos parches y características tan esperadas y solicitadas por la comunidad de usuarios.

Bien, el problema que se presentó es que tras haber configurado dicha aplicación para que la misma enviara alertas criticas por mensajes de texto (SMS) de ciertos servicios seleccionados, los destinatarios de dichos mensajes variaban según guardias de trabajo no regulares. Esto requería que cada vez que se necesitaba que un contacto recibiera notificaciones por SMS, me tuviera que sentar a copiar y adaptar las configuraciones de Icinga acorde a las necesidades. Pretender que cada uno de los notificados se configurara sus notificaciones mediante consola era demasiado, así que no me quedó otra alternativa más que trabajar, para no tener que trabajar :-P

Antes de pasar al código veamos los requisitos y consejos previos:

El script trabaja leyendo sus configuraciones de un directorio ($vconfigdir) que se define al inicio del mismo, donde deberán existir ciertos archivos que contendrán los datos variables. Se puede cambiar dicha ruta, simplemente no olviden actualizar el script reflejando los cambios.
Por defecto el directorio de configuraciones es ~/definecontacto y dentro del mismo tendrán que existir tres archivos de texto.

$vconfigdir/carpeta En su interior debe estar la ruta completa al directorio donde Icinga escribirá y buscará los archivos de contacto (una vez definidos). En mi caso utilicé la ruta /etc/icinga/objects/contacts/excepcionales. Dicho directorio debe estar declarado en la configuración de Icinga (para que los contactos sean leídos) o en un subdirectorio ya declarado.
Además de poder ser requisado por Icinga en busca de configuraciones, el directorio debe tener permisos rwxrwxrwx. Esto último es necesario para que cualquier usuario pueda escribir y borrar, de otro modo el script solo será funcional si se ejecuta como root.

$vconfigdir/lista Lista de contactos y datos necesarios. Dicha lista debe tener el siguiente formato:

#lista de contactos para icinga
#'contacto','nombre','apellido','telefono','grupo de contacto'
jperez,Juan Perez,005491166554433,soporte
mrobledo,Miguel Robledo,005491122334455,soporte-inmediato

$vconfigdir/periodos Lista de periodos de notificación. El formato de la misma es similar al anterior:

#lista de periodos de notificacion
#'nombre','descripcion'
always,Siempre
nonworkhours,Horas no laborales
workhours,Horas laborales

En todos los casos se permiten comentarios en los archivos mientras la línea empiece con el carácter numeral #.

Finalizados los requisitos, mis consejos para la ejecución del script:

Como escribí al principio de la entrada, este pequeño script se usará para que uno no deba estar realizando el trabajo de establecer las alertas que los demás precisen. Eso significa que habrá que ceder un usuario y contraseña para que las personas afectadas se conecten al host que corre Icinga, realicen los cambios y reinicien el servicio del mismo para que los cambios surjan efecto.
Lo peor que se podría hacer es pasar la contraseña de root y cruzar los dedos para que nada pase, los más precavidos preferirán usar un usuario restringido. Para el ejemplo utilicé el usuario operador.

Antes que nada modificamos el shell de usuario para reemplazarlo por la ruta al script. De ese modo se enjaula al usuario a las acciones que el script permite y nada más.

# usermod -s /usr/local/bin/definecontacto.sh operador

Cuando creen el script, haganlo en dicho PATH.

Acto seguido daremos al usuario operador los permisos necesarios para reiniciar el servicio de Icinga por medio del comando sudo sin que sea necesario introducir una contraseña. Editamos el archivo /etc/sudoers y al final del mismo agregamos lo siguiente:

Cmnd_Alias ICINGA = /etc/init.d/icinga
User_Alias ICINGAUSERS = operador
ICINGAUSERS ALL = NOPASSWD : ICINGA

Tanto en la configuración anterior, como en la línea 137 del script, se encuentra el comando que se utilizará para reiniciar el servicio de Icinga. El mismo es acorde a la gestión de sercivios de las distribuciones EL5/6 (CentOS, Red Hat, etc…). Si se pretende utilizar el script bajo otra familia de distribuciones puede que se necesite adaptar dicho comando.

Bien, cumplidos los requisitos, he aquí el código:

 Bash |  Copiar código |? 
001
#!/bin/bash
002
 
003
#definecontacto.sh
004
#Script de configuración de contactos para alertas por sms de Icinga.
005
#
006
#Dependencias:
007
# dialog >= 1.1
008
 
009
 
010
#Habilito la expansión de alias
011
shopt -s expand_aliases
012
#Directorio de configuración
013
vconfigdir=~/definecontacto
014
#Alias de dialog para incluir título y renombrar opciones
015
alias dialog='dialog --stdout --backtitle "Definir contacto de Icinga" --cancel-label 'Cancelar' --exit-label 'Salir' --yes-label 'Si''
016
#Establezco la variable de separación para  nueva linea
017
XIFS=$IFS
018
IFS=$'\n'
019
#Variables y arrays varios
020
vcarpeta=$(egrep -v '#'  $vconfigdir/carpeta)
021
alista=($(egrep -v '#' $vconfigdir/lista  | awk -F "," '{ print $1 "\n" $2 }'))
022
aperiodos=($(egrep -v '#' $vconfigdir/periodos | awk -F "," '{ print $1 "\n" $2 }'))
023
#Establezco la variable de separación a sus valores por defecto
024
IFS=$XIFS
025
 
026
 
027
#Declaro las funciones del script
028
 
029
#fcontacto Establece la variable $vcontacto
030
function fcontacto(){
031
unset vcontacto
032
vcontacto=$(dialog --title "Selección de contacto." --menu "Seleccione el contacto:" 20 80 12 "${alista[@]}" );
033
if [ $? -ne 0 ]
034
then
035
  dialog --title 'Advertencia' --msgbox "No se ha seleccionado ningún contacto." 6 80 ;
036
  fpregunta ;
037
fi
038
}
039
 
040
#fperiodo Establece la variable $vperiodo
041
function fperiodo(){
042
unset vperiodo
043
vperiodo=$(dialog --title "Selección del periodo." --menu "Seleccione el periodo deseado:" 20 80 12 "${aperiodos[@]}" );
044
if [ $? -ne 0 ]
045
then
046
  dialog --title 'Advertencia' --msgbox "No se ha seleccionado ningún periodo de notificación." 6 80 ;
047
  fpregunta ;
048
fi
049
}
050
 
051
#fpregunta Función de pregunta para loop de ejecución
052
function fpregunta(){
053
unset vpregunta
054
vpregunta=$(dialog --timeout 600 --title "¿Que desea hacer?" --menu "Seleccione una opción:" 10 80 2 "1" "Ir al menú principal" "2" "Salir" 2>/dev/null) ;
055
if [ "$vpregunta" == "1" ]
056
then
057
  finicio ;
058
else
059
  clear ;
060
  exit ;
061
fi
062
}
063
 
064
#fselecciona Muestra una lista de archivos de configuración almacenados en $vcarpeta y guardas las selecciones en $varchivo
065
function fselecciona(){
066
unset varchivo
067
if [ "$(ls -A $vcarpeta)" ]
068
then
069
  varchivo=$(dialog --title "Seleccione el archivo de alerta que desea borrar:" --fselect $vcarpeta/ 20 100 ) ;
070
  if [ $? -ne 0 ]
071
  then
072
    dialog --title 'Advertencia' --msgbox "No se ha seleccionado ningún archivo de configuración." 6 80 ;
073
    fpregunta ;
074
  fi
075
else
076
  dialog --title 'Advertencia' --msgbox "No se han encontrado archivos de configuración." 6 80 ;
077
  fpregunta ;
078
fi
079
}
080
 
081
#fborrar Borra los archivos seleccionados y almacenados en la variable $varchivo
082
function fborrar(){
083
dialog --title 'Atención' --yesno "¿Desea borrar el archivo de configuración seleccionado? $varchivo" 8 80 ;
084
if [ $? -eq 0 ]
085
then
086
  rm $varchivo
087
  if [ $? -eq 0 ]
088
  then
089
    dialog --title "¡Hecho!" --msgbox "El archivo $varchivo fue borrado, reiniciar Icinga para aplicar los cambios." 8 80 ;
090
    fpregunta ;
091
  else
092
  ferror ;
093
fi
094
else
095
  dialog --title 'Información' --msgbox "No se realizaron cambios." 6 80 ;
096
  fpregunta ;
097
fi
098
}
099
 
100
#ferror Funcion de salida para eventos no identificados
101
function ferror(){
102
dialog --title "Error" --msgbox "Ha ocurrido un error, vuelva a ejecutar el script y/o verifique la carpeta $vcarpeta." 6 80 ;
103
clear ;
104
exit ;
105
}
106
 
107
#fescribir Escribe la configuración en base a las variables seleccionadas
108
function fescribir(){
109
if [ -f $vcarpeta/sms-$vcontacto-$vperiodo.cfg ]
110
then
111
  dialog --title 'Advertencia' --msgbox "Ya existe un archivo para el usuario $vcontacto y el período de notificación $vperiodo. No se pueden establecer alertas duplicadas." 6 80 ;
112
  fpregunta ;
113
else
114
  dialog --title 'Atención' --yesno "¿Desea definir una alerta por SMS para el usuario $vcontacto en el período $vperiodo?" 6 80 ;
115
  if [ $? -eq 0 ]
116
  then
117
    echo -e "define contact{\n\t\tcontact_name\t\t\tsms-$vcontacto-$vperiodo\n\t\tuse\t\t\t\t$(cat $vconfigdir/lista | grep $vcontacto | awk -F "," '{ print $4 }')\n\t\talias\t\t\t\t$(echo "SMS $(cat $vconfigdir/lista | grep $vcontacto | awk -F "," '{ print $2 }')")\n\t\thost_notification_period\t$vperiodo\n\t\tservice_notification_period\t$vperiodo\n\t\tpager\t\t\t\t$(cat $vconfigdir/lista | grep $vcontacto | awk -F "," '{ print $3 }')\n\t\t}" > $vcarpeta/sms-$vcontacto-$vperiodo.cfg ;
118
    if [ $? -eq 0 ]
119
    then
120
      dialog --title "¡Hecho!" --msgbox "Archivo de configuración escrito correctamente. Reinicie Icinga para aplicar los cambios." 6 80 ;
121
      fpregunta ;
122
    else
123
      ferror ;
124
    fi
125
  else
126
    dialog --title "Advertencia" --msgbox "No se han efectuado cambios." 6 80 ;
127
    fpregunta ;
128
  fi
129
fi
130
}
131
 
132
#freinicia Función para reiniciar Icinga
133
function freinicia(){
134
dialog --title 'Atención' --yesno "¿Desea reiniciar el servicio de Icinga?" 6 80 ;
135
if [ $? -eq 0 ]
136
then
137
  sudo /etc/init.d/icinga restart >/dev/null;
138
  if [ $? -eq 0 ]
139
  then
140
    dialog --title "¡Hecho!" --msgbox "Servicio reiniciado." 6 80 ;
141
    fpregunta ;
142
  else
143
    ferror ;
144
  fi
145
else
146
  dialog --title "Advertencia" --msgbox "No se han efectuado cambios, por lo que cualquier configuración nueva o borrada aún no ha sido procesada por Icinga." 6 80 ;
147
  fpregunta ;
148
fi
149
}
150
 
151
#finicio Función principal que llama a las subfunciones  o termina la ejecución en base a la variable $vinicio
152
function finicio(){
153
unset vinicio
154
vinicio=$(dialog --timeout 600 --title "Menú principal" --menu "Seleccione una opción:" 12 80 4 1 "Nueva alerta" 2 "Reiniciar Icinga" 3 "Administrar alertas" 4 "Salir") ;
155
if [ $vinicio == 1 ]
156
then
157
  fcontacto ;
158
  fperiodo ;
159
  fescribir ;
160
elif [ $vinicio == 2 ]
161
then
162
  freinicia ;
163
elif [ $vinicio == 3 ]
164
then
165
  fselecciona ;
166
  fborrar ;
167
else
168
  clear ;
169
  exit ;
170
fi
171
}
172
 
173
#Finalmente llamo a la función finicio para ejecutar el script
174
finicio ;

Algunas capturas de la ventana de PuTTy con los datos del ejemplo:

definecontacto01.png
definecontacto02.png
definecontacto03.png
definecontacto04.png

Y un ejemplo del archivo que escribe el script:

cat /etc/icinga/objets/contacts/excepcionales/sms-jperez-always.cfg
define contact{
                contact_name                    sms-jperez-always
                use                             soporte
                alias                           Juan Perez
                host_notification_period        always
                service_notification_period     always
                pager                           005491166554433
                }

Espero que el script les sea de utilidad. Bye!”

PD: Dejo referencia al blog que me ayudó a configurar el envío de SMS bajo Icinga.
http://www.chriscowley.me.uk/blog/2010/05/04/sms-from-icinga-or-nagios/