bash : centraliser l’historique de vos commandes avec syslog



  • Dans cet article, je vais vous présenter une solution pour envoyer l’ensemble des commandes exécutées avec le shell bash sur un serveur syslog distant. Cette option est possible en utilisant la variable d’environnement PROMPT_COMMAND ou nativement avec bash à condition de le recompiler. C’est cette deuxième solution que je vais vous présenter avec deux alternatives : recompiler bash et l’installer directement depuis les sources ou modifier le paquet Debian. Nous verrons également une configuration rsyslog client/serveur pour centraliser tous vos logs à un seul endroit.

    Installer bash depuis les sources

    Compilation de bash avec syslog

    Voici les étapes nécessaires pour compiler bash 4.2 sur une Debian Squeeze :

    • Installez le paquet build-essential.
    • Récupérez les sources de bash : wget ftp://ftp.gnu.org/gnu/bash/bash-4.2.tar.gz
    • Décompressez l’archive et placez vous dans le répertoire de bash :
    tar xvf bash-4.2.tar.gz && cd bash-4.2
    
    • Créez un répertoire patchs et récupérez l’ensemble des patchs disponibles pour bash 4.2 :
    mkdir patchs && cd patchs
    ncftpget ftp://ftp.gnu.org/gnu/bash/bash-4.2-patches/bash42-???
    cd ..
    
    • Depuis la racine des sources, patchez bash avec tous ces patchs :
    for p in patchs/*
    do
        patch -p0 < ${p}
    done
    
    • Éditez le fichier config-top.h pour décommenter la ligne /* #define SYSLOG_HISTORY */ (tout en bas).
    • Vous pouvez ensuite compiler bash avec les options de votre choix. Par exemple, les options de compilation du paquet Debian :
    ./configure --with-curses --enable-largefile --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --enable-static-link --without-bash-malloc --bindir=/bin --host=`dpkg-architecture -qDEB_HOST_GNU_TYPE`
    
    • Reste à lancer la compilation :
    make && make install
    

    <div class=‘tip’>Attention avant de lancer le <code>make install</code>. Il écrasera tous les fichiers du paquet Debian bash. Dans le même genre, si une nouvelle version du paquet bash est installé, votre version de bash sera écrasée. Une solution est d’utiliser les diversions. Dans la même idée, conservez les sources de compilation pour faire un <code>make uninstall</code> si vous souhaitez supprimer cette version de bash.
    </div>

    Rajouter des diversions

    Pour éviter d’écraser les fichiers du paquet bash ou au contraire d’avoir la version de bash syslog écrasé par un upgrade du paquet, vous pouvez utiliser des <a href=“http://www.debian.org/doc/debian-policy/ap-pkg-diversions.html” title=“Debian Policy Manual”>diversions</a>. Avant de faire le make install, lancez cette boucle qui va créer les diversions nécessaires :

    DIVERT_FILES="/bin/bash
    /usr/share/locale/en@quot/LC_MESSAGES/bash.mo
    /usr/share/locale/af/LC_MESSAGES/bash.mo
    /usr/share/locale/id/LC_MESSAGES/bash.mo
    /usr/share/locale/tr/LC_MESSAGES/bash.mo
    /usr/share/locale/fi/LC_MESSAGES/bash.mo
    /usr/share/locale/eo/LC_MESSAGES/bash.mo
    /usr/share/locale/lt/LC_MESSAGES/bash.mo
    /usr/share/locale/pl/LC_MESSAGES/bash.mo
    /usr/share/locale/vi/LC_MESSAGES/bash.mo
    /usr/share/locale/ru/LC_MESSAGES/bash.mo
    /usr/share/locale/de/LC_MESSAGES/bash.mo
    /usr/share/locale/ca/LC_MESSAGES/bash.mo
    /usr/share/locale/pt_BR/LC_MESSAGES/bash.mo
    /usr/share/locale/et/LC_MESSAGES/bash.mo
    /usr/share/locale/sv/LC_MESSAGES/bash.mo
    /usr/share/locale/fr/LC_MESSAGES/bash.mo
    /usr/share/locale/zh_TW/LC_MESSAGES/bash.mo
    /usr/share/locale/ga/LC_MESSAGES/bash.mo
    /usr/share/locale/es/LC_MESSAGES/bash.mo
    /usr/share/locale/en@boldquot/LC_MESSAGES/bash.mo
    /usr/share/locale/hu/LC_MESSAGES/bash.mo
    /usr/share/locale/nl/LC_MESSAGES/bash.mo
    /usr/share/locale/ro/LC_MESSAGES/bash.mo
    /usr/share/locale/sk/LC_MESSAGES/bash.mo
    /usr/share/locale/ja/LC_MESSAGES/bash.mo
    /usr/share/locale/cs/LC_MESSAGES/bash.mo
    /usr/share/locale/bg/LC_MESSAGES/bash.mo"
    
    for file in $DIVERT_FILES
    do
        dpkg-divert -package "bash-syslog" -add -rename -divert ${file}_debian ${file}
    done
    

    Grâce à ces diversions, les fichiers originaux sont renommés en _debian et une mise à jour du paquet bash ne risque pas de modifier votre installation manuelle.

    Si vous souhaitez revenir au bash standard, faites un make uninstall et relancez la boucle précédente avec cette fois un remove des diversions :

    for file in $DIVERT_FILES
    do
      dpkg-divert -package "bash-syslog" -remove -rename -divert ${file}_debian ${file}
    done
    

    Modifier le paquet Debian

    C’est à mon avis la meilleure solution : pas de risque de voir ses modifications écrasées par la mise à jour du paquet, pas besoin de faire des diversions mais pour rester simple, il faudra utiliser la version de la distribution. Les étapes nécessaires à partir d’une Debian Squeeze :

    • Modifiez votre sources.list pour rajouter les paquets sources :
    # deb-src
    deb-src http://ftp.fr.debian.org/debian/ squeeze main contrib non-free
    
    • Après un apt-get update, récupérez le paquet source bash avec un apt-get source bash après vous être placé dans le répertoire /usr/local/src.
    • Installez également le paquet devscripts qui contient les outils nécessaires à la création de paquets Debian ainsi que toutes les dépendances liées à la compilation de bash :
    apt-get install devscripts
    apt-get build-dep bash
    
    • Dans le répertoire créé, bash-4.1 à l’écriture de cet article, il y a un répertoire debian. Il faut rajouter un patch dans le répertoire patches et modifier le fichier rules utilisé pour la construction du paquet. Placez vous dans l’arborécence bash-4.1/debian/patches et créez le fichier enable-syslog.dpatch avec pour contenu :
    for file in $DIVERT_FILES
    do
      dpkg-divert -package "bash-syslog" -remove -rename -divert ${file}_debian ${file}
    done
    

    Modifier le paquet Debian

    C’est à mon avis la meilleure solution : pas de risque de voir ses modifications écrasées par la mise à jour du paquet, pas besoin de faire des diversions mais pour rester simple, il faudra utiliser la version de la distribution. Les étapes nécessaires à partir d’une Debian Squeeze :

    • Modifiez votre sources.list pour rajouter les paquets sources :
    # deb-src
    deb-src http://ftp.fr.debian.org/debian/ squeeze main contrib non-free
    
    • Après un apt-get update, récupérez le paquet source bash avec un apt-get source bash après vous être placé dans le répertoire /usr/local/src.
    • Installez également le paquet devscripts qui contient les outils nécessaires à la création de paquets Debian ainsi que toutes les dépendances liées à la compilation de bash :
    apt-get install devscripts
    apt-get build-dep bash
    
    • Dans le répertoire créé, bash-4.1 à l’écriture de cet article, il y a un répertoire debian. Il faut rajouter un patch dans le répertoire patches et modifier le fichier rules utilisé pour la construction du paquet. Placez vous dans l’arborécence bash-4.1/debian/patches et créez le fichier enable-syslog.dpatch avec pour contenu :
    #! /bin/sh -e
    
    if [ $# -eq 3 -a "$2" = '-d' ]; then
        pdir="-d $3"
    elif [ $# -ne 1 ]; then
        echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
        exit 1
    fi
    case "$1" in
        -patch) patch $pdir -f --no-backup-if-mismatch -p1 < $0;;
        -unpatch) patch $pdir -f --no-backup-if-mismatch -R -p1 < $0;;
        *)
    	echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
    	exit 1
    esac
    exit 0
    
    # DP: enable syslog
    --- bash/config-top.h~	2012-09-04 23:09:48.000000000 +0200
    +++ bash/config-top.h	2012-09-04 23:09:59.000000000 +0200
    @@ -101,7 +101,7 @@
    
     /* Define if you want each line saved to the history list in bashhist.c:
        bash_add_history() to be sent to syslog(). */
    -/* #define SYSLOG_HISTORY */
    +#define SYSLOG_HISTORY */
     #if defined (SYSLOG_HISTORY)
     #  define SYSLOG_FACILITY LOG_USER
     #  define SYSLOG_LEVEL LOG_INFO
    

    Vous pouvez également changer la facilité et le niveau d’alerte syslog. Par exemple pour utiliser la facilité local1, changez :
    # define SYSLOG_FACILITY LOG_USER
    en
    # define SYSLOG_FACILITY LOG_LOCAL1

    • Dans le répertoire bash-4.1/debian, éditez le fichier rules. Il faut rajouter notre patch à la liste des patchs à appliquer aux sources de bash : recherchez la variable debian_patches (à la ligne 500 pour bash-4.1). Rajoutez à la suite des patchs enable-syslog.
    • Il faut ensuite générer ce nouveau paquet bash. Placez-vous dans le répertoire racine du paquet source bash-4.1. Pour éviter qu’il rentre en conflit avec celui livré par Debian, on rajoute un suffixe à la version du paquet ainsi qu’un petit commentaire pour le changelog du paquet :
    dch --local +syslog "Enable syslog"
    
    • On lance la fabrication du paquet avec debuild -us -uc.
    • C’est terminé : votre nouveau paquet est disponible dans /usr/local/src. Vous pouvez l’installer simplement avec dpkg -i bash_4.1-3+syslog1_*.deb.

    Configurer Rsyslog

    Après avoir installé votre nouveau bash, relancez un bash ou reconnectez vous sur votre serveur pour utiliser la nouvelle version. Après quelques commandes, vérifiez votre /var/log/syslog. Vous obtenez l’historique bash au format suivant :

    Sep  4 23:46:30 test-bash -bash: HISTORY: PID=26396 UID=0 htop
    Sep  4 23:46:33 test-bash -bash: HISTORY: PID=26396 UID=0 last
    Sep  4 23:46:40 test-bash -bash: HISTORY: PID=26396 UID=0 ll /etc/
    Sep  4 23:46:43 test-bash -bash: HISTORY: PID=26396 UID=0 less /var/log/syslog
    

    Si vous souhaitez centraliser vos logs sur un serveur, il faut modifier la configuration rsyslog de votre client et de votre serveur.

    Sur le client

    Rajoutez le fichier /etc/rsyslog.d/bash-history.conf avec pour contenu :

    # remplacez mon_loghost par l'@ip de votre serveur syslog
    user.info @mon_loghost
    

    Relancez ensuite rsyslog : service rsyslog restart.

    Sur le serveur

    Sur votre serveur syslog, créez un fichier /etc/rsyslog.d/all-bash-history.conf avec le contenu suivant :

    $template BashLogs,"/var/log/bash-history/history_%HOSTNAME%.log"
    user.info ?BashLogs
    & ~
    

    Relancez ensuite rsyslog comme pour le client après avoir créé le répertoire /var/log/bash-history : service rsyslog restart. Le répertoire /var/log/bash-history contiendra un fichier de log par serveur. Dans mon cas, j’obtiens le fichier /var/log/bash-history/history_test-bash.log qui contient :

    Sep  4 23:55:46 192.168.1.10 -bash: HISTORY: PID=26396 UID=0 less /var/log/syslog
    Sep  4 23:55:48 192.168.1.10 -bash: HISTORY: PID=26396 UID=0 top
    Sep  4 23:58:14 192.168.1.10 -bash: HISTORY: PID=26396 UID=0 service rsyslog restart
    

    Pour info, le - devant bash dans vos logs indique qu’il s’agît d’un shell de login.

    J’espère que cet article sera utile à ceux qui cherchent un moyen de centraliser et d’auditer toutes les commandes exécutées sur un ensemble de serveurs. Bons tests 😉



  • @remi Super article, de nos jours il n’y a rien de plus important que les logs !!!



  • @remi à part peut-être les métriques 😋



  • Ah… je préfère 😉