Le piège à con du jour : entiers et booléens selon Puppet

21/12/2012 by nono

J'ai une config Puppet qui commence à devenir assez touffue. On y trouve entre autres un fait md_raid qui retourne le nombre de grappes RAID logicielles sur une machine Linux. Je peux donc utiliser le fait en question pour appliquer un bout de config uniquement sur les machines qui ont des grappes RAID, typiquement pour installer l'outil de surveillance qui va avec :

if $md_raid {
  # bla bla bla
}

Cool, hein ? Hé non ! Pourquoi pas ? Parce que pour Puppet, tous les entiers sont vrais, même 0.

La bonne solution se trouve du côté de l'excellent module stdlib, qui fournit entre autres une fonction num2bool qui renvoie vrai uniquement pour les nombres strictements positifs. Mon test devient du coup :

if num2bool($md_raid) {
  # bla bla bla
}

Cette fois, ça marche. :-)

Posted in geekeries

Gnus et IMAP sur SSH

28/11/2012 by nono

Un peu de contexte pour commencer. Au boulot, mon courrier électronique est stocké sur mon PC, dans une série de boites à lettres au format Maildir, regroupées dans un répertoire appelé fort originalement ~/Maildir. À la maison, j'utilise Gnus pour lire mon courrier électronique, et je voudrais fort logiquement accéder à ces boites. Je dispose pour ça uniquement d'une connexion SSH configurée comme il faut avec les clés qui vont bien (en vrai, je pourrais avoir plus, mais ça compliquerait la config réseau).

Premier réflexe : sshfs. Ça a l'air bien sur le papier, mais ça manque sérieusement de stabilité quand il s'agit de manipuler des milliers de fichiers. À oublier donc.

Deuxième réflexe : IMAP. Dans le détail :

  • J'ai installé Dovecot sur le PC du boulot.
  • J'y ai posé dans mon home un fichier .dovecotrc qui contient la ligne suivante :
mail_location = maildir:~/Maildir:LAYOUT=fs
  • J'ai ajouté un serveur IMAP à mon Gnus :
(nnimap "licencieux.ircam.fr"
    (nnimap-stream shell)
    (imap-shell-program "ssh gomes@licencieux.ircam.fr
            /usr/lib/dovecot/imap -c .dovecotrc"))

Voilà, c'est tout ! J'aime ce genre d'outil simple et flexible. :-)

 

Posted in geekeries

NRPE, root et xinetd

16/11/2012 by nono

Ami lecteur, si tu es, comme moi, admin système, je suis prêt à parier que tu as, comme moi, un système de monitoring que tu aimerais bien faire tomber en marche. Je m'en vais ici te donner une petite magouille toute simple qui le rendra un peu moins foireux.

La machine que je vais prendre pour illustrer mon exemple est une baie SAN (iSCSI plus précisément) qui tourne sous Scientific Linux 6. Comme toutes les autres machines de mon parc, elle fait tourner NRPE et elle est surveillée par un Nagios. Le but ici est de  surveiller l'état du service tgt, qui assure la fonction de cible iSCSI.

Première étape : interroger le service depuis la machine elle-même. Ça se fait au moyen de la commande suivante :

/usr/sbin/tgtadm -C 0 --op show --mode target

Cette commande retourne la liste des cibles iSCSI définies sur la machine accompagnée d'un certain nombre d'informations à propos d'icelles (informations que j'ignorerai ici, ce n'est pas mon propos). Le premier réflexe est donc d'encapsuler cette commande dans un script shell pour en faire un greffon Nagios rudimentaire :

#!/bin/bash

ok () {
    echo "TGT OK - $*"
    exit 0
}

critical () {
    echo "TGT CRITICAL - $*"
    exit 2
}

result=$(/usr/sbin/tgtadm -C 0 --op show --mode target)
if [ $? -eq 0 ]
then
    ok $(printf "$result" | egrep '^Target')
else
    critical $result
fi

Rien de bien compliqué, n'est-ce pas ? Si ce n'est que l'utilisateur qui fait tourner NRPE n'aura probablement pas le droit de lancer la commande tgtadm et encore moins d'en tirer quoi que ce soit d'utile. Ou alors c'est que ton système est administré bizarrement.

Comment faire pour passer outre ? Ton premier réflexe sera probablement le même que le mien : mais c'est bien sur, y'a qu'à configurer sudo comme il faut et roule la galère. Sauf que l'idée me plait moyennement ; pas que je n'aie pas confiance en sudo, mais je sais pertinemment que je suis capable de le configurer comme il ne faudrait pas. Du coup j'ai pensé à une meilleure approche : utiliser xinetd.

Concrètement, j'ai commencé par ajouter un service dédié à sa config :

service tgtstatus
{
        type            = UNLISTED
        disable         = no
        bind            = 127.0.0.1
        port            = 11112
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/sbin/tgtadm
        server_args     = -C 0 --op show --mode target
        log_on_failure  += USERID
}

Tu t'empresseras de me signaler que n'importe quel utilisateur local peut, du coup, voir la configuration des cibles iSCSI. Je m'empresserai de te répondre que, d'une, c'est moins grave que de pouvoir exécuter n'importe quoi à travers une config sudo qui permet de lancer un script shell pas blindé comme il faut, et de deux, que de toute façon mes baies SAN n'ont pas d'utilisateurs locaux, manquerait plus que ça.

Du coup, l'appel à tgtadm dans mon greffon Nagios est remplacé par la ligne suivante :

result=$(/usr/bin/nc 127.0.0.1 11112)

et seul le morceau du greffon pour lequel c'est absolument nécessaire est exécuté par root, sans aucun moyen de lui passer des paramètres scabreux. C'est pas beau, ça ?

En fait, ce n'est pas si beau que ça : dans l'histoire, je viens de perdre le code de retour de tgtadm (que j'ai remplacé par celui de nc, qui est, tu en conviendras, un peu moins pertinent). Pour m'en tirer, j'ai donc dû interpréter la sortie de ma commande et pas son code de retour. Du coup j'ai laissé tomber le shell pour écrire ça dans un vrai langage de programmation, en l'occurrence Python ; voilà le résultat :

#!/usr/bin/env python
# Arnaud Gomes 2012

import sys, socket, re

# Le port du service xinetd
PORT = 11112

# Codes de retour Nagios
R_OK = 0
R_WARN = 1
R_CRIT = 2

status = ''
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', PORT))
while True:
    r = s.recv(1024)
    if not r:
        break
    status += r

if not status:
    print 'TGT WARNING - No targets defined'
    sys.exit(R_WARN)

if re.search(re.compile('^Target [0-9]+:', re.MULTILINE), status):
    output = ' '.join([re.sub('^Target [0-9]+:\s*', '', line)
                       for line in status.split('\n')
                       if re.match('^Target [0-9]+:', line)])
    print 'TGT OK - Targets %s' % output
    sys.exit(R_OK)

print 'TGT CRITICAL - %s' % status
sys.exit(R_CRIT)

Et cette fois-ci c'est bon, ça marche vraiment. :-)

Posted in geekeries

Le piège à con du jour : /bin/bash et /bin/sh

03/08/2012 by nono

Après m'être battu un petit moment contre un script de déploiement d'une appli Rails avec rvm qui foirait pour une raison inexplicable, j'ai jeté un coup d'oeil au script .rvm/scripts/rvm dans lequel j'ai trouvé ça :

# Do not allow sourcing RVM in `sh` - it's not supported
# return 0 to exit from sourcing this script without breaking sh
[[ ":$SHELLOPTS:" =~ ":posix:" ]] && return 0 || true

Mais /bin/sh, chez moi, c'est bash ! Et ben non, ça ne suffit pas.

Moralité : suffit de commencer le script par #!/bin/bash plutôt que par #!/bin/sh pour que mon déploiement se passe comme sur des roulettes. Portable, qu'on vous dit.

Posted in geekeries

Limiter les connexions par adresse IP : mauvaise idée

16/05/2012 by nono

Je gère depuis un petit moment un serveur de miroirs relativement important accessible, entre autres, via FTP et HTTP. Vu l'amour immodéré que je porte à cette relique du siècle dernier qu'est FTP, j'ai limité les ressources qu'il peut consommer pour favoriser HTTP. Entre autres, j'ai choisi de limiter le nombre de connexions simultanées à deux par adresse IP, et tant pis pour les amoureux de NAT qui devraient rejoindre ceux de FTP dans leurs 20 ans de retard.

Sauf que ça casse l'accès FTP non seulement pour les boîtes NAT, mais aussi pour l'outil de monitoring du miroir Apache, qui pour une raison ou une autre ouvre plusieurs connexions simultanément. Mauvaise idée, donc.

Grmpf.

Posted in geekeries

Utiliser Apache comme mandataire inverse

22/03/2012 by nono

Il y a quelques jours, j'ai dû (provisoirement) utiliser Apache comme mandataire inverse pour un de mes sites web. Vu que j'ai dû régler 2 ou 3 détails qui m'ont fait replonger dans la config d'Apache, un petit aide-mémoire.

Le cahier des charges : le site http://gallery.glou.org/ doit apparaître comme http://photos.glou.org/pwg/, sachant que http://photos.glou.org/ est déjà peuplé et se trouve sur une machine physique différente. Pourquoi ne pas utiliser simplement une redirection ? Simple : jusqu'à ce matin, la machine gallery.glou.org ne disposait pas d'une adresse IPv4 publique. Elle était par contre joignable normalement en IPv6. Ce problème étant résolu, la config décrite ici devrait disparaître dès que j'aurai un moment pour m'en occuper ; en attendant je la décris, elle pourrait resservir.

Travaillons d'abord sur photos.glou.org qui va jouer le rôle de mandataire. Il faut bien entendu y utiliser les modules Apache mod_proxy et mod_proxy_http pour la fonctionnalité de base ; ne pas oublier d'y ajouter mod_substitute pour réécrire les URL. Au final, la config (partielle) ressemble à ça :

LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so
LoadModule substitute_module /usr/lib/apache2/modules/mod_substitute.so

<VirtualHost *>
  ServerName photos.glou.org

  .../...

  Redirect /pwg /pwg/
  ProxyPass /pwg/ http://gallery.glou.org/
  ProxyPassReverse /pwg/ http://gallery.glou.org/

  <Location /pwg/>
    AddOutputFilterByType SUBSTITUTE text/html
    Substitute "s|http://gallery.glou.org|http://photos.glou.org/pwg|"
  </Location> 

</VirtualHost>

En l'état, ça marche mais les logs sur gallery.glou.org montreront toutes les requêtes comme provenant du mandataire. On va donc indiquer à Apache (sur gallery, donc, cette fois-ci) d'utiliser le format combined classique pour les requêtes directes et d'indiquer l'adresse d'origine véritable en plus de celle du mandataire pour les requêtes qu'il relaie. Ça se dit comme ça :

# Une copie du format combined standard, au cas ou.
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined-std
LogFormat "%{X-Forwarded-For}i (via %h) %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined-proxy

SetEnvIf X-Forwarded-For ".+" proxiedrequest
CustomLog logs/proxy_log combined-std env=!proxiedrequest
CustomLog logs/proxy_log combined-proxy env=proxiedrequest

Voilà, maintenant ça juste marche.

Posted in geekeries

Les prochains concerts des Fourmis acidulées

25/02/2012 by nono

Pas moins de trois concerts prévus pour les deux mois qui viennent :

  • Le 17 mars à l'Époque, 81 rue du Cardinal Lemoine, Paris 5ème, à l'occasion de la St Patrick.
  • Le 24 mars au Mood's, 13 passage du Moulinet, Paris 13ème, en compagnie de Coverbusters ; entrée 10 euros avec une boisson, ou 8 euros en prévente auprès du groupe (par mail à preventes@fourmis-acidulees.fr ou en cliquant ici).
  • Le 14 avril au Cavern, 21 rue Dauphine, Paris 6ème.

On vous y attend nombreux !

Posted in musique

Les vieux sont de retour

25/02/2012 by nono

Dans la série «les vieux sont de retour», je suis en train d'écouter le nouveau Van Halen, a Different Kind Of Truth, avec nul autre que David Lee Roth au chant. Une fois passé le premier morceau (Tattoo, je crois que c'est aussi le premier single, et il est, disons, dispensable), on les retrouve comme on les avait quittés il y a 25 ans. Encore ! Very Happy

Posted in musique

Remettre les objectifs en face des trous avec exiftool

12/02/2012 by nono

Un peu de contexte : j'ai un appareil photo Pentax K200D et un petit tas de vieux objectifs des années 60-70 entièrement manuels. Bien entendu, ces vieux objectifs (montés sur le boîtier via un adaptateur m42-Pentax K) n'embarquent aucune électronique, et le boîtier est donc incapable de les reconnaître. Tout au plus connaît-il à peu près leur focale : l'utilisateur (c'est moi :-) ) l'indique à la main pour régler le stabilisateur. À peu près, parce que l'interface de réglage ne connaît que certaines valeurs courantes (par exemple, pas moyen de régler le boîtier sur 105mm, je me rabats sur 100mm qui est la valeur possible la plus proche).

Du coup j'ai un peu joué avec exiftool pour remettre les données EXIF en face des trous. Par exemple, pour le concert de vendredi dernier, j'ai utilisé mes trois Takumar (systématiquement à pleine ouverture, ça me simplifie la tâche) ; j'utilise le bout de script suivant pour enregistrer les infos pertinentes dans les photos :

cd /le/repertoire/ou/j/ai/mis/mes/photos
exiftool -FocalLength="105.0 mm" -FNumber=2.8 \
    -FocalLengthIn35mmFormat="157.5 mm" \
    -LensModel="SMC Takumar 105mm f/2.8" \
    -if '$focallength eq "100.0 mm"' -ext jpg .
exiftool -FNumber=1.8 \
    -LensModel="Super Takumar 55mm f/1.8" \
    -if '$focallength eq "55.0 mm"' -ext jpg .
exiftool -FNumber=3.5 \
    -LensModel="Super Takumar 35mm f/3.5" \
    -if '$focallength eq "35.0 mm"' -ext jpg .
rm *_original

Et voilà, c'est cuit ! :-)

Posted in geekeries photos

Les Fourmis au Mood's le 24 mars

08/02/2012 by nono

Nous partagerons à nouveau la scène avec les Coverbusters le 24 mars prochain. Ça se passe au Mood's, près de Tolbiac, à Paris 13ème. Plus de détails sur le site des Fourmis.

Les pré-ventes sont à 8 euros avec une conso (au lieu de 10 sur place) en écrivant au groupe (preventes@fourmis-acidulees.fr) ou en cliquant ci-dessous.

Posted in musique