dimanche 16 juin 2013

Fabric, la toolbox des champions

Fabric, mon rêve d'automatisation.

Mon aventure avec Fabric ne fait que débuter et commence sur 2 constats et problématiques :
  • La lecture des posts suivants : vos 5ères minutes sur un serveur (blog.nicolargo.com, plusbryan.com)
  • La répétition des commandes et l'application de changement à grande échelle.
C'est vrai, je fais quoi durant mes 5ères minutes, je me souviens pas toujours.
Et puis j'en ai marre de répéter toujours les mêmes commandes.
J'aurais pu faire des scripts en bash, je les ai déjà mais bof.
Je ne veux pas installer un serveur d'application et déployer des clients pour automatiser.
Je ne veux pas faire du ruby.
Je ne veux une solution agile.
Je veux pouvoir le transmettre à mes collègues sans les forcer.
Je veux faire du python.

Donc pas de Puppet, ni Chef même si ça a l'air très bien.

Heureusement je découvre Fabric.
Notamment ses infos :
Je décide de regrouper mes 2 problématiques standardisation et automatisation.

Setup serveur initial

Mes 5 min sur un serveur :

  1. installer fail2ban
  2. installer cron-apt
  3. installer logwatch
  4. Mettre a jour l'environnement (PS1, .vimrc, .bashrc)
  5. installer shorewall (sans le configurer)

Fabric

Traduit en Fabric ca donne :


from fabric.api import *
from cuisine import *
from fabric.colors import cyan,magenta,red
from fabric.contrib.files import comment, uncomment, contains, exists, append, sed

@task
def PS1_host():
   append('/root/.bashrc','export PS1=\'\[\033[01;31m\]\u\[\033[01;33m\]@\[\033[01;36m\]\h \[\033[01;33m\]\w \[\033[01;35m\]\$ \[\033[00m\]\'',use_sudo=False)

@task
def update_upgrade():
    run('aptitude update && aptitude full-upgrade')

@task
def vim_color():
    append('/root/.vimrc','syntax on')

@task
def cront_apt_setup():
    if not package_ensure_apt('cron-apt','update=False')
    append('/etc/cron-apt/config','APTCOMMAND=/usr/bin/aptitude')
    append('/etc/cron-apt/config','ACTIONDIR="/etc/cron-apt/action.d"')
    append('/etc/cron-apt/config','MAILTO="moi@gmail.com"')
    append('/etc/cron-apt/config','ERROR="/var/log/cron-apt/error"')
    append('/etc/cron-apt/config','LOG="/var/log/cron-apt/log"')
    append('/etc/cron-apt/config','LOG="/var/log/cron-apt/log"')
    append('/etc/cron-apt/config','MAILON="always"')
    append('/etc/cron-apt/config','SYSLOGON="upgrade"')
    append('/etc/cron-apt/config','OPTIONS="-o quiet=1 -o Dir::Etc::SourceList=/etc/apt/sources.list"')
    file_append('/etc/cron-apt/action.d/5-install','autoclean -y\n safe-upgrade -y -o APT::Get::Show-Upgraded=true')

@task
def logwatch():
    if not package_ensure_apt('logwatch','update=False'):
   run('aptitudsilverstone install -y logwatch')
   run('cp -a /usr/share/logwatch/default.conf/* /etc/logwatch/conf/')
   run('cp -a /usr/share/logwatch/scripts/* /etc/logwatch/scripts/')
   run('mkdir -p /var/cache/logwatch')
   sed('/etc/logwatch/conf/logwatch.conf',before='MailTo = root',after='MailTo = moi@gmail.com')
   sed('/etc/logwatch/conf/logwatch.conf',before='Detail = Low',after='Detail = Med')
   run('logwatch')

@task
def shorewall_install():
    if not package_ensure_apt('shorewall','update=False')
    print(red("Don't forget to configure SHOREWALL"))

@task
def install_fail2ban():
if not package_ensute_apt('fail2ban','update=False')
sed('/etc/fail2ban/jail.conf',before='destemail = root@localdomain',after='destemail=moi@gmail.com')
run('service fail2ban restart')

Bien sur ce post reflète mon expérience actuelle avec Fabric, je ne le maîtrise pas encore mais ça me permet déjà de faire des trucs très sympas, de standardiser et d'automatiser.

Par exemple, reste a créer une task install appelant les autres, de créer un organisation répertoire/fichiers, de piocher les hosts dans la base glpi et mettre tout ca dans un svn.

Fabric est très complet, permet déxecuter toutes les taches courantes, installer des paquets, gérer les utilisateurs/groupes, les services, ...
Le tout en python, Fabric peut donc être inclut dans d'autre projets.

Derniers petits trucs pour la route

Par défaut Fabric recherche son fabfile.py dans le répertoire courant ou bien s'il est spécifié à l'execution :
fab -f /home/someplace/fabfile.py

Mais Fabricpermet de créer un fichier .fabricrc qui spécifiant l'emplacement du fabfile.py, par exemple :
#cat .fabricrc 
fabfile=/home/FABRIC/fabfile.py
export $fabfile

De cette facon on peut executer directement fab -l pour voir la liste des commandes :
$ fab -l
Available commands:
    Instalacion_SVN_1_7_8  Instalacion de SVN CollabNet 1.7

Dernier truc qui m'a couté avant dý parvenir charger une list d'host a partir d'un fichier :
@task
def host_list():
        env.warns_only = 'True'
        with open('/home/julien/caf/caf/1-list.org') as fd:
         env.hosts = [x.strip() for x in fd]


De cette facon je peux combiner les commandes et installer logwatch sur tous les hosts défini dans ma liste.
fab host_list logwatch

Je peux également paralélliser l'installation par groupe de 5 :
fab host_list logwatch -P -z 5

Enfin, dernier conseil la documentation est très bien faite, très complète et facile a lire. La communauté est reactive par IRC ou mailing list.
L'essayer c'est l'adopter.




mardi 9 avril 2013

Au secours je peux plus entrer

En migrant de version de proxmox ou d'OpenVZ des CT Ubuntu.
Je me trouve enfermé dehors, pas ce vzctl enter, pas de ssh


root@x ~ # vzctl enter 600
enter into CT 600 failed
Unable to open pty: No such file or directory

Oups, beaucoup de recherche sur le internet mais beaucoup de solutions utilisant des CT Centos.
J'ai finalement trouvé une solution que me convient, les recréer dans /dev.


root@x ~ # vzctl exec 600 "cd /dev; /sbin/MAKEDEV pty"

root@x ~ # vzctl enter 600

Par contre je n'ai pas trouvé de solution permanente.
J'ai bien essayé les conseils désactivé udev, supprimer, etc ... sans succès.

En attendant je redémarre pas souvent et ça marche

lundi 28 janvier 2013

Jouer avec les FS et les clusters

Je réinstalle un cluster, je souhaite monter mon FS ext4 qui était en cluster pour récupérer les données du backup.

Mais impossible :
Skipping Cluster Volume group

Remede, desactivé le lock lvm pour ce VG, puis l'activer, l'importer et le monter.
vgchange -cn vgname --config 'global {locking_type = 0}'
vgchange -ay vgname
vgimport vgname
lvchange -ay /dev/mapper/vgname-backup--gfs


Et maintenant comment faire pour monter directement dans mon nouveau cluster mon FS GFS2 ?
Erreur :
/sbin/mount.gfs: fs is for a different cluster 
/sbin/mount.gfs: error mounting lockproto lock_dlm

Facile, on récrit sur la metadata, la table du lock.
 gfs2_tool sb /dev/mapper/vgGFS-lvGFS table nouveacluster:nouveaupointdemontage
 mount /dev/mapper/vgGFS-lvGFS /u01/



lundi 7 janvier 2013

Udev rules pour disk ASM

RHEL 6.3 n'étant pas certifié par Oracle, pas d'outils oracleasm pour créer des disk.
Obliger de passer par d'autres méthodes (multipath, mknod) ou bien des règles udev.

Je préfère les règles udev car elles permettent de préciser le repertoire souhaité, propiétaire et permissions et bien plus...

Le plus simple est de créer une nouvelle règle. Elles sont appliquées par ordre.
99.asm.rules sera donc appliqué en dernier. Important la nom doit terminer par ".rules"
On remplace le numéro de DM par * pour éviter les changement la filtre se base sur le numéro de série.

Pour trouver le numéro de série
Regarder /etc/multipath/wwids
ou bien : ls -al /dev/disk/by-id
ou encore : udevadm info --query=all --path=$(udevadm info -q path -n /dev/mapper/mpathc)

Exmple de contenu :
KERNEL=="dm-*",SUBSYSTEM=="block",ENV{DEVTYPE}=="disk",ENV{DM_UUID}=="mpath-2001738000f87036c",NAME+="oracleasm/disks/DSK1",OWNER="grid",GROUP="oinstall",MODE="0660"

KERNEL=="dm-*",SUBSYSTEM=="block",ENV{DEVTYPE}=="disk",ENV{DM_UUID}=="mpath-2001738000f87036d",NAME+="oracleasm/disks/DSK2",OWNER="grid",GROUP="oinstall", MODE="0660"

KERNEL=="dm-*",SUBSYSTEM=="block",ENV{DEVTYPE}=="disk",ENV{DM_UUID}=="mpath-2001738000f87036e",NAME+="oracleasm/disks/DSK3",OWNER="grid",GROUP="oinstall",MODE="0660"

KERNEL=="dm-*",SUBSYSTEM=="block",ENV{DEVTYPE}=="disk",ENV{DM_UUID}=="mpath-2001738000f87036f",NAME+="oracleasm/disks/DSK4",OWNER="grid",GROUP="oinstall",MODE="0660"

KERNEL=="dm-*",SUBSYSTEM=="block",ENV{DEVTYPE}=="disk",ENV{DM_UUID}=="mpath-2001738000f870370",NAME+="oracleasm/disks/DSK5",OWNER="grid",GROUP="oinstall",MODE="0660"

Pour appliquer la règle sans redémarrer :
udevadm trigger

jeudi 25 octobre 2012

Candy, chat are no dead yet

Candy est un chat en javascript qui semble très flexible et dispose de plus en plus de plugin.
http://candy-chat.github.com/candy/


Il s'intègre bien avec Openfire même si c'est un peu compliqué la première fois.
Je l'ai par exemple couplé avec Openfire, lui même couplé avec le LDAP de Zimbra pour créer un chat room pour les utilisateurs.

Config Openfire


Dans la paramètres du serveur activé HTTP Binding.
Activlé les ports 7070 et 7443.
Activé le script syntax : Allows BOSH.
Laisser ar défaut la Cross-domain policy.

Installation Candy


Télécharger Candy dans votre répertoire www.
Définir votre vhost.
La difficulté est dans Rewrite rule

RewriteRule http-bind/ http://monserver.com:7070/http-bind/ [P]


Config vhost


<VirtualHost *:8081>
ServerName mon.server.com
DocumentRoot /var/www/candy/
<Directory />
                Options FollowSymLinks
                AllowOverride All
</Directory>
<Directory /var/www/candy>
               Options Indexes FollowSymLinks MultiViews
              AllowOverride All
              Order allow,deny
              allow from all
</Directory>
             AddDefaultCharset UTF-8
            Options +MultiViews
            RewriteEngine On
            RewriteRule http-bind/ http://monserver.com:7070/http-bind/ [P]
</VirtualHost>

Config cany/index.html 


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Candy - Chats are not dead yet</title>
<link rel="shortcut icon" href="res/img/favicon.png" type="image/gif" />
<link rel="stylesheet" type="text/css" href="res/default.css" />
<link rel="stylesheet" type="text/css" href="candy-chat-candy-plugins-e9310e4/colors/candy.css" />
        <link rel="stylesheet" type="text/css" href="candy-chat-candy-plugins-e9310e4/roomPanel/default.css" />
        <link rel="stylesheet" type="text/css" href="candy-chat-candy-plugins-e9310e4/inline-images/candy.css" />

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<script type="text/javascript" src="libs/libs.min.js"></script>
<script type="text/javascript" src="candy.min.js"></script>
<script type="text/javascript" src="candy-chat-candy-plugins-e9310e4/colors/candy.js"></script>
        <script type="text/javascript" src="candy-chat-candy-plugins-e9310e4/inline-images/candy.js"></script>
        <script type="text/javascript" src="candy-chat-candy-plugins-e9310e4/roomPanel/roomPanel.js"></script>

<script type="text/javascript">
$(document).ready(function() {
Candy.init( 'http://monserveur.com/http-bind/', {
core: { debug: false, autojoin: ['info@conference.monserver.com' ]},
view: { resources: 'res/', language: 'fr'}
});

// enable Colors plugin (default: 8 colors)
                        CandyShop.Colors.init();
CandyShop.InlineImages.init();
// enable RoomPanel plugin
                        CandyShop.RoomPanel.init({
                                // domain that hosts the muc rooms, only required if autoDetectRooms is enabled
                                mucDomain: 'info.monserver.com',

                                // allow you to force a list of rooms, only required if autoDetectRoom is disabled
                                roomList: [
                                       {
                                                name: 'info',
                                                jid:  'info@monserver.com'
                                        },
                                                                       ],
                                // show room list if all rooms are closed, default value is true. [optional]
                                showIfAllTabClosed: true,
                                // detect rooms before showing list, default value is true. [optional]
                                autoDetectRooms: true,
                                // how long in seconds before refreshing room list, default value is 600. [optional]
                                roomCacheTime: 600
                        });
Candy.Core.connect();
});
</script>
</head>
<body>
<div id="candy"></div>
</body>
</html>

Merci à Candy


Le support est assuré au travers de google group, la communauté Candy est très active.
Merci à eux.
https://groups.google.com/forum/#!forum/candy-chat


vendredi 5 octobre 2012

Zabbix superviser Postfix

Superviser Postfix pour éviter par exemple que des emails restent bloquer sans s'en appercevoir.
Recette: un zabbix, un template, un petit script et l'erreur est corrigée.

Zabbix Postfix Template

Template Zabbix-Postfix
Les items, 2 triggers et un graph détaillant les items. Ce template est ccompatible Zabbix 2.0

Installer les outils

Installer sur les serveurs les outils suivants : pflogsumm et logcheck

Config Zabbix agent

Pour récupérer l'était de la queue, on déclare un Userparmeter qui exécutera la commande suivante ;

UserParameter=postfix.mailq,mailq | grep -v "Mail queue is empty" | grep -c '^[0-9A-Z]'

Script Zabbix-Postfix

Créer le script suivant qui une fois les logs analyser, envoi les données au moyen de zabbix_sender au serveur qui actualisera les items correspodants.
#!/bin/bash +x
PFLOGSUMM=/usr/sbin/pflogsumm.pl
MAILLOG=/var/log/mail.log
LOGTAIL=/usr/sbin/logtail
DAT1=/tmp/zabbix-postfix-offset.dat
DAT2=$(mktemp)
ZABBIX_SENDER=/usr/bin/zabbix_sender
ZABBIX_HOST=monserver #même nom que dans Zabbix
ZABBIX_SERVER=monserverzabbix.com
ZABBIX_CONF=/etc/zabbix/zabbix_agentd.conf
DEBUG=0

function zsend {
 key="postfix.`echo "$1" | tr ' -' '_' | tr '[A-Z]' '[a-z]' | tr -cd [a-z_]`"
 value=`grep -m 1 "$1" $DAT2 | awk '{print $1}'`

 [ ${DEBUG} -ne 0 ] && echo "Send key \"${key}\" with value \"${value}\"" >&2
 $ZABBIX_SENDER -s $ZABBIX_HOST -z $ZABBIX_SERVER -c $ZABBIX_CONF -k "${key}" -o "${value}" 2>&1 >/dev/null
}

$LOGTAIL -f $MAILLOG -o $DAT1 | $PFLOGSUMM -h 0 -u 0 --bounce_detail=0 --deferral_detail=0 --reject_detail=0 --no_no_msg_size --smtpd_warning_detail=0 > $DAT2

zsend received
zsend delivered
zsend forwarded
zsend deferred
zsend bounced
zsend rejected
zsend held
zsend discarded
zsend "reject warnings"
zsend "bytes received"
zsend "bytes delivered"
zsend senders
zsend recipients

rm $DAT2

Automatiser le script

Toutes les minutes

* * * * * /etc/zabbix/zabbix-postfix.sh

Astuce supprimer les emails bloqués en queue

# perl -e 'foreach (`postqueue -p`) {`postsuper -d $1` if /^([0-9A-Z]+)/}'


Remerciements

http://blog.hbis.fr/2012/03/30/zabbix-postfix_monitoring/
http://www.zabbix.com/wiki/howto/monitor/mail/postfix/monitoringpostfix

mardi 28 août 2012

Fail2ban + Asterisk 1.8


Fail2ban est souvent utilisé avec Asterisk pour sécuriser les connexions, éviter les fraudes.
Mais depuis la version 1.8 le format des log a quelque peu changé.
Le port de l'utilisateur distant a été ajouté et par conséquent les filtres Asterisk existant sont inopérants.

Par conséquend modifier comme suit la configuration de votre jail pour Asterisk.

NOTICE.* .*: Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - Wrong password
NOTICE.* .*: Registration from '\".*\".*' failed for '<HOST>(:[0-9]{1,5})?' - No matching peer found

La première ligne permet de bloquer les connexions intempestive.
La seconde bloque les appels anonymes ou les appels entrants venant de peer inconnu.