Le blog des salariés

Aller au contenu | Aller au menu | Aller à la recherche

jeudi, avril 10 2014

Backporter un package Debian testing vers Debian stable

On souhaite backporter un package de testing vers la stable. En l'occurrence, pour notre exemple on prendra le package python-numpy pour illustrer les manipulations.

Prérequis

Forger un paquet debian, peut parfois prendre des allures de champs de bataille, surtout lorsque le paquet en question a un certain nombre de dépendance. Pour cloisonner le travail, je vous propose d'utiliser deboostrap.

On créer un environnement ::

apt-get install debootstrap debootstrap --arch amd64 wheezy ~/dbs-builddeb http://ftp.fr.debian.org/debian/

On se chroot dans le debootstrap ::

chroot dbs-builddeb

Nous allons avoir besoin de quelques outils de développement, que nous installons ::

apt-get install devscripts build-essential dh-buildinfo echo "export LANG=C" >> ~/.bashrc

Howto par l'exemple

On configure apt dans /etc/apt/source.list, tel que ::

  

## Wheezy deb http://ftp.fr.debian.org/debian wheezy main deb-src http://ftp.fr.debian.org/debian wheezy main # wheezy-backports deb http://ftp.fr.debian.org/debian wheezy-backports main contrib non-free ## Jessie #deb http://ftp.fr.debian.org/debian jessie main deb-src http://ftp.fr.debian.org/debian jessie main

On update le tout

apt-get update

On récupère les sources

apt-get source python-numpy

On récupère les dépendances, que l'on installe

apt-get build-dep python-numpy

On compile le code source

cd python-numpy-1.8.1 dch -i

python-numpy (1:1.8.1-1~etalabbpo70+1) unstable; urgency=low * Non-maintainer upload. * Backport to wheezy. -- Felix Defrance <felix.defrance@data.gouv.fr> Thu, 10 Apr 2014 14:22:32 +0000

dpkg-buildpackage -tc

C'est terminé ! On peut voir le package forgé dans le répertoire parent.

python-numpy_1.8.1-1~etalabbpo70+1.debian.tar.gz python-numpy_1.8.1-1~etalabbpo70+1_amd64.deb python-numpy_1.8.1-1~etalabbpo70+1.dsc python-numpy_1.8.1-1~etalabbpo70+1_amd64.changes

Installation du package

Pour une utilisation personnelle un dpkg -i suffira, sinon on ajoutera le package à un depot spécifiquement établi pour l'occasion par exemple..

mercredi, décembre 11 2013

Active/Backup iptables tracking connexions between two gateway

This setup is interesting when you want to avoid SPOF on your firewall/gateway which are on top of your network architecture.

This article is about how to improve high availability on stateful firewalls using netfilter's conntrack synchronization. In a later article we will discuss on how to automatically remove static routes when a gateway is down (Gateway Fail Over Wan)

Need stateful mode

Stateful based firewalling is now used on most part of firewalling architectures. The stateful mode is based on keeping track of the network connections to make sysadmin's life better ;)

To view active conntrack and deal with it, you could install conntrack package. it will provide this kind of commands :

conntrack -S (Show statistics)

or

conntrack -L (List conntrack)

Stateful Syncing between nodes

In our use case, we need to synchronize network connections tracking on two firewalls nodes. This is ensured by a daemon called conntrackd

apt-get install conntrackd

Conntrackd, has three replication approaches, “no track”, “ft-fw” and “alarm”.

  • no-track: use the best effort syncing tables and no control was made when tables are replicate.
  • ft-fw: use reliable protocol to perform message tracking. So that sync error or corruption are permitted.
  • alarm: Which allow to set syncing tables interval. This option require a lot of bandwhitch.

More information: http://conntrack-tools.netfilter.org/manual.html#sync

We choose ft-fw mode because it's ready for production environnement, more stable and it works well.

To use ft-fw, you could reuse example as your configuration and make some little changes, as your network addresses.

zcat /usr/share/doc/conntrackd/examples/sync/ftfw/conntrackd.conf.gz > /etc/conntrackd/conntrackd.conf

Conntrackd, should start as daemon at boot starting, so we define this by init scripts and /etc/default/conntrackd in Debian.

Iptables Rules

As you drop all undesired traffic, we need to add some rules to allow traffic came from conntrackd on both nodes:

# ------------------------- Conntrack
iptables -A INPUT -p udp -i $IFCONN -d 225.0.0.50/32 --dport 3780 -j ACCEPT
iptables -A INPUT -p udp -i $IFCONN -s $IPCONN  --dport 694 -j ACCEPT

Check your synchronisation

As your configuration should work without any problem, now we could play with the daemons.

Conntrackd, provide commands that they works like a client/server. So we can ask conntrackd by cli commands to know cache / statistics /etc..

Here are some examples :

To show tables which are synchronised , we could use this commands. See external cache (cache which is on gw02 was synchronised to gw01):

root@gw02:~# conntrackd -e 

See internal cache :

root@gw02:~# conntrackd -i

You can compare results and counting them :

root@gw02:~# conntrackd -e | wc -l
root@gw02:~# 325
root@gw01:~# conntrackd -i | wc -l
root@gw02:~# 328

And show more statistics :

conntrackd -s

As you can see, ft-fw is asynchronous. Our setup is “Active-Backup”. You can sync mannually for fun:

root@gw02:~# conntrackd -n

Conntrackd, provide Active-Active setup but it's still in asymmetric mode. For more information you can read the manual : http://conntrack-tools.netfilter.org/manual.html#sync-aa

mardi, novembre 5 2013

Handling misencoded HTTP request in Python WSGI applications

At Easter-eggs we use Python and WSGI for web applications development.

The last few months some of our applications crashed periodically. Thanks to WebError ErrorMiddleware, we receive an email each time an internal server error occurs.

For example someone tried to retrieve all of our french territories data with the API.

The problem is simple: when the request headers contains non UTF-8 characters, the WebOb Request object throws an UnicodeDecodeError exception because it expects the headers to be encoded in UTF-8.

End-user tools like web browsers generate valid UTF-8 requests with no effort, but non UTF-8 requests can be generated by some odd softwares or by hand from a ipython shell.

Let's dive into the problem in ipython :

In [1]: url = u'http://www.easter-eggs.com/é'

In [2]: url
Out[2]: u'http://www.easter-eggs.com/\xe9'

In [3]: url.encode('utf-8')
Out[3]: 'http://www.easter-eggs.com/\xc3\xa9'

In [4]: latin1_url = url.encode('latin1')
Out[4]: 'http://www.easter-eggs.com/\xe9'

In [5]: latin1_url.decode('utf-8')
[... skipped ...]
UnicodeDecodeError: 'utf8' codec can't decode byte 0xe9 in position 27: unexpected end of data

This shows that U+00E9 is the Unicode codepoint for the 'é' character (see Wikipedia), that its UTF-8 encoding are the 2 bytes '\xc3\xa9', and that decoding in UTF-8 a latin1 byte throws an error.

The stack trace attached to the error e-mails helped us to find that the UnicodeDecodeError exception occurs when calling one of these Request methods: path_info, script_name and params.

So we wrote a new WSGI middleware to reject mis-encoded requests, returning a bad request HTTP error code to the client.

from webob.dec import wsgify
import webob.exc


@wsgify.middleware
def reject_misencoded_requests(req, app, exception_class=None):
    """WSGI middleware that returns an HTTP error (bad request by default) if the request attributes
    are not encoded in UTF-8.
    """
    if exception_class is None:
        exception_class = webob.exc.HTTPBadRequest
    try:
        req.path_info
        req.script_name
        req.params
    except UnicodeDecodeError:
        return exception_class(u'The request URL and its parameters must be encoded in UTF-8.')
    return req.get_response(app)

The source code of this middleware is published on Gitorious: reject-misencoded-requests

We could have guessed the encoding, and set the Request.encoding attribute, but it would have fixed only the read of PATH_INFO and SCRIPT_NAME, and not the POST and GET parameters which are expected to be encoded only in UTF-8.

That's why we simply return a 400 bad request HTTP code to our users. This is simpler and does the work.

mardi, octobre 22 2013

Validation en masse d'adresses mail

mail Pour le besoin d'un de nos clients, j'ai eu à valider dans un script python un très grand nombre d'adresse e-mails. En y pensant cette situation est courante : combien de bases de données clients contiennent un grand nombre d'adresse mail qui, pour certaines, ont pu être saisies des années auparavant, sans forcément de validation efficace (double opt-in par exemple). On imagine bien ainsi qu'en utilisant une telle adresse mail des années plus tard, rien n'est moins sûr que notre mail arrive à destination. C'est pourquoi il nous a été utile d'écrire un script capable de détecter les adresses mails assurément invalides d'une base de données.

Pour la réalisation de ce script (écrit en python), je me suis tout d'abord en toute logique tourné vers une librairie qui me semblait parfaitement adaptée validate_email. Cette librairie implémente une méthodologie en plusieurs étapes :

  1. Une validation syntaxique de l'adresse mail pour commencer ;
  2. Une validation du nom de domaine en récupérant via une requête DNS le serveur de mail du domaine (enregistrement MX) ;
  3. Vérification du serveur mail en s'y connectant, en vérifiant la réponse en cas d'une commande HELO du protocole SMTP, voire même de sa réponse en cas d'un test d'envoi de mail à l'adresse à vérifier (commande SMPT RCPT TO) ;

Il est par ailleurs possible de définir jusqu’où on souhaite pousser la validation : syntaxique uniquement, syntaxique + validation DNS du MX ou sinon validation complète.

Mes premières utilisations de cette librairie m'ont démontré que son utilisation pour une validation en masse d'adresses mail n'était pas du tout optimale (+ de 24heures pour la validation d'environ 70 000 adresses mails même incomplètes). J'ai alors développé une librairie similaire optimisant les phases 2 et 3. En effet pourquoi valider plusieurs fois un même nom de domaine ou encore pourquoi valider une connexion SMTP à un même serveur de mail. Voici donc une librairie reprenant cette méthodologie et l'optimisant pour une validation en masse, en insérant simplement un mécanisme de mise en cache des vérifications communes à un même domaine. Pour vous donner une idée de l'optimisation apportée, une validation d'environ 70 000 adresses mails (validation syntaxique + validation d'une connexion MX) prend environ 1h30 à 2h. Cette librairie dénommée mass_validate_email est disponible ici et publié sous licence LGPL.

vendredi, septembre 27 2013

When CEPH comes to rescue

Ceph

Here @Easter-eggs[1], like others, we start playing with the awesome CEPH[2] distributed object storage. Our current use of it is the hosting of virtual machines disks.

Our first cluster was just installed this week on tuesday. Some non production virtual machines where installed on it and the whole cluster added to our monitoring systems.

Cluster

On thursday evening, one of the cluster nodes went down due to cpu overhead (to be investigated, looks like a fan problem).

Monitoring systems send us alerts as usual, and we discovered that CEPH just did the job :) :

  • the server lost was detected by other nodes
  • CEPH started to replicate pgs between other nodes to maintain our replication level (this introduced a bit of load on virtual machines during the sync)
  • virtual machines that were running on the dead node were not alive anymore, but we just add to manually start them on another node (pacemaker is going to be setup on this cluster to manage this automagically)

On friday morning, we repaired the dead server, and boot it again:

  • the server automatically joined the CEPH cluster again
  • osd on this server were added automatically in the cluster
  • replication started to get an optimal replication state

Incident closed!

What to say else?

  • thanks to CEPH and the principle of server redundancy to let us sleep in our home instead of working a night in the datacenter
  • thanks to CEPH for being so magical
  • let's start the next step: configure pacemaker for automatic virtual machines failover on cluster nodes

Notes

[1] http://www.easter-eggs.com/

[2] http://ceph.com/

jeudi, septembre 26 2013

Superviser la synchronisation de vos annuaires OpenLDAP

Logo OpenLDAP Cette problématique semble peut-être simple de prime abord, mais une supervision efficace de la synchronisation d'annuaires OpenLDAP n'est pas aussi triviale qu'elle peut en avoir l'air. Toute la complexité réside dans le mécanisme relativement simpliste de réplication avec syncrepl : un schéma LDAP périmé ou des ACL mal définies, peut facilement entraîner une désynchronisation de vos annuaires sans que cela soit très visible.

Le mécanisme de réplication syncrepl se base sur des identifiants de versions des données contenues dans l'annuaire, pour déterminer quelles informations doivent être répliquées et quelles informations est la plus à jour (dans le cas d'une réplication master-master). Ces identifiants de versions sont stockés dans l'attribut contextCSN de la racine de l'annuaire et dans les attributs entryCSN de chacun des objets de l'annuaire. Les valeurs de ces attributs (obligatoirement indexés) sont construites à l'aide de la date de dernière modification. Cela permet, via l'overlay syncrepl d'OpenLDAP, de déterminer à partir du contextCSN d'un répliqua, les objets LDAP de l'annuaire source modifiés depuis et qui devront donc être synchronisés. La réplication d'un objet consiste ensuite à transférer l'objet complet d'un annuaire à l'autre, sans distinction d'attributs : tous les attributs seront répliqués quelle que soit la modification l'ayant entraînée. Ce mécanisme très simple n'est malheureusement pas très robuste et des cas de désynchronisation son relativement fréquents. Une bonne supervision est alors indispensable, d'autant plus qu'une synchronisation en panne n'empêche pas pour autant un répliqua de répondre aux requêtes qui lui sont adressées.

Un plugin de check Nagios (ou Icinga) existait déjà mais il se basait uniquement sur la valeur du contextCSN des annuaires, sans vérification objet par objet, voire attribut par attribut. Il pouvait alors laisser passer une désynchronisation.

J'ai donc eu l'occasion d'en développer un qui, selon moi, aborde plus globalement la supervision d'une réplication syncrepl. Ce plugin ne se contentera donc par simplement de vérifier les valeurs des attributs contextCSN, mais permettra une vérification des objets présents dans chacun des annuaires, de la valeur de leur attribut entryCSN, voire même de la valeur de l'ensemble de leurs attributs. Il est évident qu'une supervision plus exhaustive sera plus coûteuse en terme de ressource, et c'est pourquoi j'ai voulu, à travers différents paramètres, permettre une vérification plus ou moins complète de l'état de synchronisation :

  • --filter : il est possible de ne vérifier qu'une partie des objets de l'annuaire, en spécifiant un filtre de recherche LDAP
  • --no-check-contextCSN : permet de désactiver la vérification du contextCSN des annuaires
  • --attributes : permet d'activer la validation des valeurs de tous les attributs de tous les objets des annuaires

Il est a noter cependant, que la supervision la plus complète sur un annuaire d'environ 10 000 objets, ne prend que quelques secondes (entre 3 et 10 secondes en fonction de la charge des serveurs).

Pour télécharger ce plugin, c'est ici

Exemple d'utilisation :

check_syncrepl_extended \
     -p ldap://ldap0.example.lan \
     -c ldap://ldap1.example.lan/ \
     -D 'uid=nagios,ou=sysaccounts,o=example' \
     -P 'password' \
     -b 'o=example' -a -n

Définition de la command correspondante dans Nagios :

define command {
        command_name    check_syncrepl
        command_line    /usr/local/lib/nagios/plugins/check_syncrepl_extended -p $ARG1$ -c ldap://$HOSTADDRESS$/ -b $ARG2$ -D '$ARG3$' -P '$ARG4$' -a -n
}

Définition du service correspondant :

define service{
        use                           generic-service
        service_description     LDAP Syncrepl
        check_command         check_syncrepl!ldap://ldap0.example.lan!o=example!uid=nagios,ou=sysaccounts,o=example!password
        host_name                ldap1
}

mardi, septembre 24 2013

[Libvirt] Migrating from on disk raw images to RBD storage

Ceph

As we just configured our first CEPH[1] cluster, we needed to move our current virtual machines (using raw images stored on standard filesystem) so they use the RBD block device provided by CEPH.

We use Libvirt[2] and Kvm[3] to manage our virtual machines.

Libvirt

Migration with virtual machine downtime




This step can be done offline:

  • stop the virtual machine
 virsh shutdown vmfoo
  • convert the image to rbd
 qemu-img convert -O rbd /var/lib/libvirt/images/vmfoo.img rbd:libvirt-pool/vmfoo
  • update the VM configuration file
 virsh edit vmfoo
 <disk type='file' device='disk'>
   <driver name='qemu' type='raw' cache='none'/>
   <source file='/var/lib/libvirt/images/vmfoo.img'/>
   <target dev='vda' bus='virtio'/>
   <alias name='virtio-disk0'/>
   <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
 </disk>

devient:

 <disk type='network' device='disk'>
   <driver name='qemu'/>
   <auth username='libvirt'>
     <secret type='ceph' uuid='sec-ret-uu-id'/>
   </auth>
   <source protocol='rbd' name='libvirt-pool/vmfoo'>
     <host name='10.0.0.1' port='6789'/>
     <host name='10.0.0.2' port='6789'/>
     ...
   </source>
   <target dev='vda' bus='virtio'/>
   <alias name='virtio-disk0'/>
   <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
 </disk>
  • restart the virtual machine
virsh start vmfoo

Migration without downtime

The trick here is to use migration support in libvirt/kvm and the ability to provide a different xml definition for the target virtual machine:

  • get the current vm disk informations
 qemu-img info /var/lib/libvirt/images/vmfoo.img
  • create an empty rbd of the same size
 qemu-img create -f rbd rbd:libvirt-pool/vmfoo XXG
  • get the current vm configuration
 virsh dumpxml vmfoo > vmfoo.xml
  • edit this configuration to replace the on disk image by the rbd one
 <disk type='file' device='disk'>
   <driver name='qemu' type='raw' cache='none'/>
   <source file='/var/lib/libvirt/images/vmfoo.img'/>
   <target dev='vda' bus='virtio'/>
   <alias name='virtio-disk0'/>
   <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
 </disk>

devient:

 <disk type='network' device='disk'>
   <driver name='qemu'/>
   <auth username='libvirt'>
     <secret type='ceph' uuid='sec-ret-uu-id'/>
   </auth>
   <source protocol='rbd' name='libvirt-pool/vmfoo'>
     <host name='10.0.0.1' port='6789'/>
     <host name='10.0.0.2' port='6789'/>
     ...
   </source>
   <target dev='vda' bus='virtio'/>
   <alias name='virtio-disk0'/>
   <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
 </disk>
  • start the migration process
virsh migrate --live --persistent --copy-storage-all --verbose --xml vmfoo.xml vmfoo qemu+ssh://target_node/system
  • wait until the process finished. The time to wait depends of your cluster performances and your VM size, but there is no interruption of the virtual machine!
  • you're done, your virtual machine is now running over rbd and once checked you can safelly archive or destroy your old disk image.

Notes:

  • of course you have to use libvirt/kvm with rbd support on target node
  • you have to use a recent version of kvm, we had memory exhaustion problems on the hypervisor during the migration process with debian wheezy version

Notes

[1] http://ceph.com/

[2] http://libvirt.org/

[3] http://www.linux-kvm.org/

Convert an unsparse vm image to sparse vm image

Convert an unsparse vm image to sparse vm image

Few weeks ago, I needed to convert qcow2 image to raw image. So, I executed this command:

qemu-img convert -f qcow2 -O raw vm-foo.qcow2 vm-foo.raw

After that, I had an unsparse image because qemu-img don't output sparse file. I saw this by running this command:

qemu-img info vm-foo.img

or

ls -lksh vm-foo.img

So now, I want to convert this new vm-image to a sparse file, because I want to free space in my file system. As you could know, in sparse file, zero-data, don't takes place in your file system instead of unsparse file.

Moreover, when files are deleted, their data stay in place on the disk (just indexes was deleted).

In my case, i want to optimize my future sparse file vm-image, and I decide to force zero-data in my vm-image.

So, on my started guest, I wrote zero-data as far as possible, using this command:

root@foo# dd if=/dev/zero of=/tmp/zerotxt bs=1M
root@foo# sync
root@foo# rm /tmp/zerotxt

Now, I shutdown the guest, and convert unsparse file to sparsed file by using cp command:

cp --sparse=always vm-foo.raw vm-foo.raw-sparse

Well done, I got a clean sparse file!

  qemu-img info vm-foo.raw-sparse
image: vm-foo.raw-sparse
file format: raw
virtual size: 40G (42949672960 bytes)
disk size: 6.3G
This article on my blog.

jeudi, septembre 19 2013

Mailt : l'outil indispensable pour tester vos serveurs de mail

mail Lors de la mise en place d'un serveur de mail, à un moment ou un autre, on aura toujours besoin d'envoyer un mail de test pour tester une connexion IMAP ou POP. Pour faciliter tout cela, nous avons mis au point une boite à outils bien pratique, que nous avons nommée Mailt. Elle se compose de trois outils (pour le moment) :

  • smtpt : envoyez un mail en une commande au serveur SMTP de votre choix, en définissant simplement le destinataire, l'expéditeur ou encore le contenu du mail. Fini les connexions telnet manuelle à coup de copier/coller pour simuler les différents cas de figure que vous souhaitez expérimenter ! Cette commande sera d'autant plus pratique si vous souhaitez valider l'efficacité de votre analyse anti-spam et/ou anti-virus :
    • le paramètre --spam vous permettra de facilement adapter le contenu du mail, afin qu'il contienne la chaîne de caractères de test GTUBE qui sera interprété comme un spam par votre anti-spam.
    • le paramètre --virus vous permettra, de la même manière, d'insérer dans le contenu du mail la chaîne de caractères de test EICAR qui sera interprété comme un virus par votre anti-virus.

Vous pourrez également facilement valider une connexion STARTTLS ou SMTPS, authentifiée ou non, et avec le paramètre --debug, ce sera comme si vous tapiez tout cela manuellement dans une session telnet ou openssl s_client.

  • imapt : testez en une commande la connexion à un serveur IMAP de votre choix. Fournissez simplement les informations de connexion (utilisateur, mot de passe, serveur, port, sécurité SSL, dossier INBOX, etc.) et cette commande validera pour vous la réussite d'une connexion, en affichant le nombre de messages contenus dans le dossier de votre choix. Vous pourrez facilement ajuster le niveau de détail de vos tests avec les paramètres --verbose ou --debug
  • popt : testez en une commande la connexion à un serveur POP de votre choix. De la même manière, à partir de paramètres fournis, cette commande validera pour vous la connexion au serveur de votre choix et vous affichera le nombre de mails sur le serveur.

Cette suite d'outils est écrite en Python et utilise des librairies standards, le plus souvent déjà présentes sur vos serveurs (paquet Debian python-support). Elle est facilement installable au travers d'un paquet Debian très léger, téléchargeable ici ou en ajoutant le repos Debian suivant et installer le paquet mailt :

deb http://debian.zionetrix.net/debian/ squeeze mailt

Remarque : Ces paquets sont également disponibles pour la version testing de Debian (Wheezy).

vendredi, septembre 13 2013

How to self published your code with Git over http

Introduction

Today i want to publish my scripts. Few days ago, I decided to use Git to release them. But it's only visible by me on my servers. So i decided to use Viewgit, a web interface in php. It's cool! Now, i can see my scripts with my browser! But in fact, I'm unhappy because nobody is able to use git mechanism like “git clone”. So, I want to use “git over http”, with git-http-backend.

For this environment, I use Nginx web server over Debian to serve files.

Viewgit

The installation of viewgit is pretty easy, just download, untar and play. You must drop your git projects, in “projects” directory, like me :

/var/www/viewgit/projects

And declare your projects in /var/www/viewgit/inc/localconfig.php

Your nginx config looks like this at this time :

vi /etc/nginx/sites-available/viewgit
server {
listen 10.0.0.6:80;
root /var/www/viewgit;
index index.php;
server_name git.d2france.fr;
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9001;
}

Git over http

Before using git over http, you need to know two fundamentals. First, you want to allow people to download your projects, and second, you want to allow people to make modifications on your projects.

To play around git clone, fetch and pull requests, git uses http.uploadpack service.

To play around git push, git uses http.receivepack service.

To provide those services, your need to use GIT-HTTP-BACKEND as a backend cgi script for your web server and nginx cgi server (fcgiwrap) to run it.

apt-get install git-http-backend fcgiwrap

With Nginx, the configuration could be like this :

server {
listen 10.0.0.6:80;
root /var/www/viewgit;
index index.php;
server_name git.d2france.fr;
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9001;
}
location ~ ^projects/.*/(HEAD|info/refs|objects/info/.*|git-upload-pack)$ {
root /var/www/viewgit/projects;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME   /usr/lib/git-core/git-http-backend;
fastcgi_param PATH_INFO         $uri;
fastcgi_param GIT_PROJECT_ROOT  /var/www/viewgit/projects;
fastcgi_param GIT_HTTP_EXPORT_ALL "";
fastcgi_pass unix:/var/run/fcgiwrap.socket;
}
}

Here, i just want to share my scripts. So, I only allow git-upload-pack requests


It works!

Now you can clone your git repositories with this command:

 git clone http://server/projects/foobar

As you can see, on each project in viewgit you can't add any information like the url of your git. A friend made a plugin for that. You should find his work at viewgit-projectinfos-plugin.

This article on my blog.

mercredi, avril 17 2013

Dokuwiki : une page d'accès refusé personnalisée

Logo Dokuwiki Lorsqu'un utilisateur accède à votre wiki Dokuwiki alors qu'il n'en a pas le droit, un message l'informe que l'accès à cette page lui est interdit et lui suggère de s'authentifier. Ce message ne correspond pas forcément à la réalité en fonction de l'utilisation que vous faites de votre wiki. Il peut être intéressant alors d'avoir une page personnalisable qui avec vos propres mots, expliquera à l'utilisateur pourquoi il obtient cette page ou encore comment accéder à la page souhaitée.

Dans cette optique, j'ai écrit un plugin Dokuwiki dénommé deniedpage permettant de définir une page de votre wiki sur laquelle l'utilisateur sera redirigé automatiquement en cas d'accès refusé à une page. Vous pourrez définir la page de votre choix en utilisant la page de configuration de la section administration. Comme n'importe quelle autre page de votre wiki, vous pourrez créer, et plus tard modifier cette page, en utilisant l'éditeur en ligne.

Grâce au gestionnaire d’extensions de Dokuwiki, l'installation de ce plugin se fait très simplement en copiant l'URL suivante dans le champ de téléchargement et en cliquant sur le bouton Télécharger :

https://github.com/brenard/dokuwiki-plugin-deniedpage/zipball/master

La mise à jour se fera ensuite tout aussi simplement en utilisant le bouton de Mettre à jour. Penser à activer le plugin après son installation et assurez- vous que votre page d'erreur personnalisée soit accessible à n'importe qui. Pour plus d'information sur ce plugin, vous pouvez consulter sa page sur le site Dokuwiki.org.

jeudi, mars 28 2013

Dokuwiki : Authentification LDAP + HTTP

Logo Dokuwiki Pour un de nos clients, la problématique suivante s'est posée : afin de supporter l'authentification SSO en place dans son infrastructure, il était nécessaire que Dokuwiki n'authentifie pas directement les utilisateurs mais fasse confiance à l'authentification effectué par Apache. Pour cela, Dokuwiki, avec son système de plugin d'authentification, implémente une solution relativement simple :

  • Dokuwiki (core) récupère les informations d'authentification fournies par Apache et les propose au plugin via la méthode trustExternal()
  • Les plugins ayant implémenté cette méthode, utilisent les informations d'authentification fournies pour authentifier l'utilisateur sans avoir besoin de lui afficher un formulaire.

Si comme nous, vous avez besoin de récupérer par ailleurs des informations sur vos utilisateurs Dokuwiki dans un annuaire LDAP tout en faisant confiance à l'authentification faite par Apache, vous serez heureux d'apprendre que c'est désormais possible. En effet, le plugin d'authentification LDAP de Dokuwiki (authldap) n'implémentait pas jusqu'ici cette méthode trustExternal() et affichait donc systématiquement un formulaire à l'utilisateur, quand bien même celui-ci avait déjà été authentifié par Apache. Nous avons implémenté cette méthode et l'avons proposé au projet Dokuwiki. Pour voir la Pull Request correspondante sur Github, c'est ici

lundi, août 23 2010

Disable IPv6 autoconfiguration at startup

On a LAN with IPv6 autoconfiguration enabled (using a radvd service for example), it is often needed to set static addresses for servers and so deactivate IPv6 autoconf on them.

With Debian 5.0 at least, it should be as easy as adding:

pre-up sysctl -w net.ipv6.conf.eth0.autoconf=0

in /etc/network/interfaces. But it doesn't works, because unless you set up some IPv6 adresses before in the init process, the ipv6 module is not loaded and so net.ipv6 doesn't exist. To fix this, just explicitely add ipv6 in /etc/modules...

Same things happens if you wan't to disable RA with net.ipv6.conf.IFACE.accept_ra=0

vendredi, septembre 25 2009

I've lost my files !!!

Bonjour,

À qui cela n'est-il donc jamais arrivé ???

Avec le système de fichiers ext2 il 'y avait la possibilité de retrouver des fichiers effacés à l'aide de Midnight Commander mais avec Ext3 que néni.

Après quelques recherches, j'ai découvert ext3undel. Celui-ci peut être utiliser directement, avec ses options, ou bien propose deux autres exécutables, gabi et ralf qui sont plus simples d'utilisations mais plus globaux.

Ext3undel s'appuie, entre autre, sur foremost, disponible en paquets Debian (Lenny).

Foremost permet de restaurer des fichiers effacés du système en spécifiant des types de fichier, la partition ou image dd concernée, un répertoire de destination des fichiers restaurés ainsi que quelques autres options... Il a l'avantage de pouvoir travailler dur une partition montée ce qui n'est pas forcément le mieux pour éviter l'écrasement d'inodes mais permet de travailler sur des filsystem que l'on ne peut pas démonter ou monter en readonly.

Dans le cas présent, après avoir créer le répertoire de destination, j'ai utilisé la commande :

foremost -s 512 -o /root/photo-finds/ -t jpg /dev/md1

Le résultat est surprenant, pour un répertoire effacé d'une taille d'environ 5 Go, il a récupéré 199 Go de fichiers correspondant au type et sur la partition que j'avais spécifié. Foremost a donc restauré des fichiers effacés depuis longtemps :)

mardi, mai 5 2009

Support d'Internet Explorer 8 chez Easter-eggs

Easter-eggs franchit le pas et supporte désormais Microsoft Internet Explorer 8.

Le logiciel nous a été livré ce matin aux alentours de midi par un livreur en scooter. Quelques salariés ont eu l'occasion de le goûter.

Internet Explorer 8

Promesse tenue par Microsoft : la version 8 du navigateur est plus sécurisée que ses versions précédentes. En effet, nous avons reçu un coup de fil avant livraison nous demandant si nous étions sûrs de bien vouloir commander. L'installation est rapide : seulement une demi-heure d'attente avant livraison.

jeudi, janvier 22 2009

Symfony et grep

J'ai écrit un nouveau plugin minimaliste facilitant l'utilisation de la commande grep dans le framework Symfony.

Il est implémenté comme une «task» Symfony.

Il est désormais possible de faire des recherches dans le code source du projet Symfony à l'intérieur des actions, des classes du modèle, des formulaires, des filtres et des templates.

Il y a un fichier de configuration pour régler les répertoires et fichiers exclus par défaut, ainsi que les options par défaut passées à grep.

Quelques exemples :

  • recherche de getContactInformation dans tout le code source (en excluant les répertoires de cache, les plugins, etc.) :
symfony grep getContactInformation

L'option -n affiche la ligne grep qui aurait été exécutée :

symfony grep getContactInformation -n
grep "getContactInformation" -r --color=always -i -n --include=*.php --include=*.css --include=*.js --include=*.yml --include=*.ini --exclude-dir=./lib/model/om --exclude-dir=./lib/model/map --exclude-dir=./lib/form/base --exclude-dir=./lib/filter/base --exclude-dir=./cache --exclude-dir=./plugins .
  • recherche de "Nouveau" dans les templates et dans les formulaires
$ symfony grep Nouveau --templates --forms -n
$ grep "Nouveau" -r --color=always -i -n ./apps/*/modules/*/templates ./lib/form/*.php

lundi, janvier 19 2009

Vim surround

J'aimerais présenter l'extension Surround qui permet de jouer avec les délimiteurs.

Ce plugin permet d'ajouter, supprimer ou remplacer n'importe quel délimiteur : parenthèses, crochets, tags HTML ou autre.

Exemple :

var_dump($contact["name"]);

Remplaçons les guillemets par des quotes avec cs"' :

var_dump($contact['name']);

Supprimons var_dump avec dw puis les parenthèses avec ds( :

$contact['name'];

Mais c'est là que je gagne surtout du temps : si je veux utiliser la fonction format_text() en lui donnant comme paramètre $contact'name', je sélectionne en mode visual avec la souris le texte (sans le point-virgule) puis je tape sf puis je tape le nom de la fonction et Entrée. Cela donne :

format_text($contact['name']);

Pour que cela fonctionne il faut avoir placé dans le ~/.vimrc :

vmap <Leader>s <Plug>Vsurround
set mouse=a

Veuillez consulter la doc pour plus d'exemples sur ce plugin redoutable.

vendredi, janvier 16 2009

2.6.26 et HP Proliant ML 350 G*

Quelque petits soucis lors d'un upgrade kernel sur un HP Proliant ML350 G3.

L'action : mise à jour noyau du 2.6.18-6-686 Debian vers un 2.6.25-bpo.1-686 puis 2.6.26-bpo.1-686

Le résultat : après les reboot nous obtenions :

[ 115.293610] virtual[3035]: segfault at 9bd844b8 ip b7c92d5b sp bfcde0d0 error 4 in libc-2.3.6.so[b7b96000+127000]
[ 117.156483] smokeping[3029]: segfault at 9be1c4b8 ip b7f5ed5b sp bfbec9ac error 4 in libc-2.3.6.so[b7e62000+127000]
[ 119.843435] authdaemond[2700]: segfault at 9bfa34b8 ip b7ebed5b sp bfe551b0 error 4 in libc-2.3.6.so[b7dc2000+127000]
[ 119.850857] authdaemond[3193]: segfault at 9bfa34b8 ip b7ebed5b sp bfe551b0 error 4 in libc-2.3.6.so[b7dc2000+127000]
[ 119.861912] authdaemond[3197]: segfault at 9bfa34b8 ip b7ebed5b sp bfe551b0 error 4 in libc-2.3.6.so[b7dc2000+127000]
[ 119.881931] authdaemond[3204]: segfault at 9bfa34b8 ip b7ebed5b sp bfe551b0 error 4 in libc-2.3.6.so[b7dc2000+127000]
[ 123.437760] authdaemond[3209]: segfault at 9bfa34b8 ip b7ebed5b sp bfe551b0 error 4 in libc-2.3.6.so[b7dc2000+127000]
[ 126.109079] sympa.pl[3223]: segfault at 9b9884b8 ip b7e94d5b sp bfb22d6c error 4 in libc-2.3.6.so[b7d98000+127000]
[ 126.122140] authdaemond[3215]: segfault at 9bfa34b8 ip b7ebed5b sp bfe551b0 error 4 in libc-2.3.6.so[b7dc2000+127000]
[ 126.510816] authdaemond[3225]: segfault at 9bfa34b8 ip b7ebed5b sp bfe551b0 error 4 in libc-2.3.6.so[b7dc2000+127000]
[ 127.022884] archived.pl[3237]: segfault at 9b9da4b8 ip b7ee5d5b sp bfb745ac error 4 in libc-2.3.6.so[b7de9000+127000]
[ 127.936428] task_manager.pl[3240]: segfault at 9ba634b8 ip b7f6ed5b sp bfffba2c error 4 in libc-2.3.6.so[b7e72000+127000]

avec les deux version et reproductible à chaque fois.

La libc faisant plus que rarement des segfaults nous sommes orientés vers un problème mémoire puis matériel mais après moult tests, que néni, rien de tout cela.

En grattant un peu plus loin nous avons trouvé dans /var/log/dmesg.*.gz :

[ 0.000000] ------------[ cut here ]------------
[ 0.000000] WARNING: at arch/x86/kernel/rtc.c:124 mach_get_cmos_time+0xb6/0x161()
[ 0.000000] Modules linked in:
[ 0.000000] Pid: 0, comm: swapper Not tainted 2.6.26-bpo.1-686 #1
[ 0.000000] [<c0122587>] warn_on_slowpath+0x40/0x66
[ 0.000000] [<c02b42ea>] cpu_init+0x233/0x23b
[ 0.000000] [<c0122e00>] vprintk+0x21f/0x2e1
[ 0.000000] [<c0389f31>] init_apic_mappings+0x2a8/0x2c2
[ 0.000000] [<c02b9dab>] _spin_lock_irqsave+0x16/0x2f
[ 0.000000] [<c02b9e39>] _spin_unlock_irqrestore+0xd/0x10
[ 0.000000] [<c0122a2d>] release_console_sem+0x173/0x18c
[ 0.000000] [<c0122eb6>] vprintk+0x2d5/0x2e1
[ 0.000000] [<c0108f00>] fpregs_get+0x20/0xcc
[ 0.000000] [<c0391f1d>] __alloc_bootmem_core+0x129/0x2ba
[ 0.000000] [<c010872b>] rtc_cmos_read+0x5f/0x66
[ 0.000000] [<c01089c9>] mach_get_cmos_time+0xb6/0x161
[ 0.000000] [<c01088d5>] read_persistent_clock+0x14/0x27
[ 0.000000] [<c0390792>] timekeeping_init+0xc/0x12f
[ 0.000000] [<c03902b3>] pidhash_init+0x5f/0x8a
[ 0.000000] [<c037f722>] start_kernel+0x19b/0x2d7
[ 0.000000] =======================
[ 0.000000] ---[ end trace 4eaa2a86a8e2da22 ]---0

Ouch! vilain.

Puis grâce à ce cher Google nous avons découvert ce joli bug RTC du kernel qui semble être spécifique aux HP Prolaint ML350 G*

https://bugs.launchpad.net/debian/+source/linux-2.6/+bug/314378

En suivant le lien redhat-bugs #451188 en haut de page nous constatons qu'il est signalé que ce bug est corrigé dans la branche Git du 2.6.27 de Linus.

Un peu de patience avant les upgrades sur ce type de hardware :).

Propel Criteria Builder

Symfony propose les ORM Propel ou Doctrine par défaut.

L'ORM est censé simplifié l'écriture des requêtes. Cependant le développeur maîtrisant bien le langage SQL saura sans difficulté exprimer une requête SQL mais devra réfléchir pour être capable de l'exprimer dans l'ORM.

Si vous utilisez Propel, voici un site qui propose de construire le Criteria Propel à partir d'une requête SQL, ou même d'une sous-partie de requête SQL.

Par exemple, si j'entre ceci :

contact.id NOT IN (1,2,3)

Le code suivant sera généré :

$c = new Criteria();
$crit0 = $c->getNewCriterion(ContactPeer::ID, array(1,2,3), Criteria::NOT_IN);
 
// Perform  at level 0 ($crit0 )
 
 
// Remember to change the peer class here for the correct one in your model
$c->add($crit0);
$result = TablePeer::doSelect($c);
 
// This loop will of course need to be edited to work
foreach ($result as $obj)
{
	//$val = $obj->getValue();
}

Reste à adapter ce code à notre application.

mardi, janvier 13 2009

Vim aligne

Par défaut Vim ne permet pas d'aligner verticalement plusieurs lignes entre-elles et cela me manque.

Je m'explique, prenons ce code (moche) :

array(
   'id' => 23,
   'name' => 'Jean-Charles Huet',
   'age' => 58
   )

Nous aimerions qu'il ressemble à :

array(
   'id'   => 23,
   'name' => 'Jean-Charles Huet',
   'age'  => 58
   )

Le plugin Vim «Align» permet cela : http://www.vim.org/scripts/script.p....

Sélectionner les lignes avec Shift-v puis taper

:Align=>

Cela fonctionne avec n'importe quel(s) caractère(s) d'alignement donc on peut aligner des affectations, etc.

- page 1 de 2