Mot-clé - planet-libre

Fil des billets

vendredi 26 août 2016

Updatengine : désinstaller un logiciel avant d'en installer un nouveau

Nous avons déjà parlé d'Updatengine dans ces pages : c'est un logiciel libre de déploiement de logiciels pour Windows composé de clients sur chaque poste contrôlés par un serveur développé sous Python/Django. Je l'utilise avec bonheur en production sur un parc d'une trentaine de machines avec grande satisfaction.

Récemment, j'ai cherché à désinstaller un logiciel avant d'en installer la mise à jour.

Possibilité 1 : le logiciel est déployé avec Windows Installer

Si le logiciel a été déployé avec Windows Installer, alors l'utilitaire "wmic" permet de le désinstaller. Le script de désinstallation pourra alors ressembler à :

wmic product where "name like 'Logiciel%'" call uninstall
logiciel-nouvelle-version.exe /s
section_end
download_no_restart

Par exemple, pour désinstaller les anciennes versions de Java avant d'en installer une nouvelle, on pourra utiliser :

wmic product where "name like 'Java%'" call uninstall
jre-8u101-windows-x64.exe /s
section_end
download_no_restart

Possibilité 2 : s'il n'est pas visible/désinstallable avec WMIC

On peut alors simplement exécuter le désinstallateur (à condition d'en connaître le chemin) :

IF EXIST "C:\Program Files\Logiciel\uninstall.exe" ("C:\Program Files\Logiciel\uninstall.exe" /s Logiciel-nouvelle-version-install.exe /s) ELSE (Logiciel-nouvelle-version-install.exe /s) )

Par exemple pour SumatraPDF, lecteur PDF libre pour Windows, cela pourra devenir :

IF EXIST "C:\Program Files\SumatraPDF\uninstall.exe" ("C:\Program Files\SumatraPDF\uninstall.exe" /s SumatraPDF-3.1.2-install.exe /s) ELSE (IF EXIST "C:\Program Files (x86)\SumatraPDF\uninstall.exe" ("C:\Program Files (x86)\SumatraPDF\uninstall.exe" /s SumatraPDF-3.1.2-install.exe /s) ELSE (SumatraPDF-3.1.2-install.exe /s) )

Bon entretien de vos machines !

dimanche 3 juillet 2016

Des statistiques libres avec Rstudio, déployé en quelques minutes

R est un puissant outil et langage d'analyse statistique. S'il est possible d'installer tout le nécessaire à l'utilisation de R sur un poste, Rstudio est une plaisante alternative avec une utilisation via le navigateur des outils hébergés sur un serveur. Cela peut se révéler pratique pour éviter un déploiement sur des postes clients et permettre aux utilisateurs de travailler sur leurs données en tout lieu.

Nous allons voir ici comment installer Rstudio en quelques étapes faciles.

Installation de base

On considère être sur une version de Debian stable (par ex. actuellement Jessie).

apt install r-base
apt install gdebi-core
wget https://download2.rstudio.org/srtudio-server-0.99.902-amd64.deb
gdebi rstudio-serveur-0.99.902-amd64.deb

Il est possible que la version la plus récente de rstudio-server ne soit pas celle donnée ici. C’est pourquoi il est conseillé de visiter https://www.rstudio.com/products/rstudio/download-server/.

À l'issue de cette étape, le serveur Rstudio doit être actif et accessible sur le port 8787 : http://localhost:8787 (on remplacera localhost par le nom d'hôte ou l'adresse IP routable de la machine si elle est distante).

Plaçons Apache en reverse proxy devant

On considère ici qu'Apache est déjà présent sur la machine, sinon on l'installera par apt install apache2.

Dans le fichier /etc/apache2/sites-available/rstudio.conf, on place le contenu suivant :

<VirtualHost *:80>
  ServerName rstudio.domaine.tld
  <Proxy *>
    Allow from localhost
  </Proxy>
 
  ProxyPassMatch ^/p/([0-9]+)/(websocket|.*/websocket)/$ ws://localhost:8787/p/$1/$2/
  ProxyPass / http://localhost:8787/
  ProxyPassReverse / http://localhost:8787/
  ProxyRequests Off
</VirtualHost>

On active alors le module proxy d'Apache puis le site :

a2enmod proxy_http
service apache2 restart
a2ensite rstudio.conf

Et dans /etc/rstudio/rserver.conf, on place la ligne suivante :

www-address=127.0.0.1

Un petit coup de certbot pour l'HTTPS

Récupérons maintenant un certificat HTTPS via Certbot :

certbot –apache

Le tour est joué, rstudio est désormais accessible derrière https://rstudio.domaine.tld

Autorisations d'accès à Rstudio

Pour la gestion des profils, Rstudio utilise les utilisateurs locaux de la machine. Nous allons ajouter la ligne suivante dans /etc/rstudio/rserver.conf :

auth-required-user-group=rstudio-users

Ainsi, seuls les utilisateurs faisant partie du groupe rstudio-users pourront utiliser Rstudio. Il ne reste plus qu'à créer les utilisateurs et les placer dans le bon groupe !

P.S. Merci à Brendan qui m'a aidé pour ce déploiement et cet article !

samedi 4 juin 2016

vnstat sur Raspberry Pi pour surveiller le trafic réseau

Nous allons voir ici comment installer vnstat pour surveiller le trafic réseau et afficher une petite page de synthèse sur l'utilisation du trafic. Cela peut-être utile par exemple pour mesurer le trafic traversant une passerelle Raspberry Pi construite tel que raconté ici.

vnstat en ligne de commande

Tout commence avec (e.g. sous Raspbian Jessie) :

apt install vnstat vnstati

Demandons alors à vnstat de créer une base de données du trafic pour l'interface que l'on veut surveiller :

vnstat -i eth0 -u

Désormais, un appel à la commande vnstat affiche en ligne de commande une synthèse sur le trafic réseau :

vnstat -u #Mise à jour des informations
vnstat #Affichage de la synthèse
Database updated: Sat Jun  4 13:02:00 2016

   eth0 since 29/05/16

          rx:  136.26 MiB      tx:  411.92 MiB      total:  548.18 MiB

   monthly
                     rx      |     tx      |    total    |   avg. rate
     ------------------------+-------------+-------------+---------------
       May '16    134.72 MiB |  410.23 MiB |  544.94 MiB |    1.67 kbit/s
       Jun '16      1.55 MiB |    1.69 MiB |    3.24 MiB |    0.09 kbit/s
     ------------------------+-------------+-------------+---------------
     estimated         8 MiB |       8 MiB |      16 MiB |

   daily
                     rx      |     tx      |    total    |   avg. rate
     ------------------------+-------------+-------------+---------------
      29/05/16    134.72 MiB |  410.23 MiB |  544.94 MiB |   51.67 kbit/s
         today      1.55 MiB |    1.69 MiB |    3.24 MiB |    0.57 kbit/s
     ------------------------+-------------+-------------+---------------
     estimated         1 MiB |       1 MiB |       2 MiB |

vnstat sur une page web

vnstati est une commande parente de vnstat qui génère une image de synthèse plutôt qu'un tableau. Pratique pour nous, êtres humains, qui aimons la bigarrure ! Alors demandons à vnstati de nous géréner quelques images à l'aide de ce script que l'on pourra placer dans cron :

#!/bin/bash
vnstat -u -i eth0
vnstati -s -i eth0 -o /var/www/html/summary.png
vnstati -h -i eth0 -o /var/www/html/hourly.png
vnstati -d -i eth0 -o /var/www/html/daily.png
vnstati -t -i eth0 -o /var/www/html/top10.png
vnstati -m -i eth0 -o /var/www/html/monthly.png

Et pour afficher ces images, nous allons utiliser une petite page web et nginx :

apt install nginx

puis remplaçons la page par défaut /var/www/html/index.nginx-debian.html par index.html contenant :

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Statistics</title>
</head>

<body>
<h2 align="center">Network Statistics</h2>
<hr align="center">
<p align="center"><img src="summary.png" alt="Summary"/><br/>
  Summary
</p>
<hr align="center">
<p align="center"><img src="hourly.png" alt="Traffic stats on a hourly basis for the last 24 hours "/><br/>
  Traffic stats on a hourly basis for the last 24 hours
</p>
<hr align="center">
<p align="center"><img src="daily.png" alt="Traffic stats on a daily basis for the last 30 days"/><br/>
  Traffic stats on a daily basis for the last 30 days
</p>
<hr align="center">
<p align="center"><img src="monthly.png" alt="Traffic stats on a monthly basis for the last 12 months"/><br/>
  Traffic stats on a monthly basis for the last 12 months
</p>
<hr align="center">
<p align="center"></p>
<p align="center"><img src="top10.png" alt="All time top 10 traffic days"/><br/>
  All time top 10 traffic days</p>
<hr align="center">
</body>
</html>

et si l'on pointe un navigateur vers l'adresse IP du Raspberry Pi, on voit alors s'afficher :

Screenshot_2016-06-04_15-28-00.png

Un Raspberry Pi en passerelle IPv4, pour surveiller des flux réseaux par exemple

Nous allons voir dans ce billet comment paramétrer un Rasperry Pi pour qu'il joue le rôle de passerelle IPv4. Attention, avec son interface ethernet 100 Mbps et sa puissance limitée, il est évident que le montage présenté ici peut convenir dans un environnement domestique mais sans doute pas au-delà.

Matériel

Prenons donc un Raspberry Bi (muni de Raspbian Jessie) et munissons-le d'un port ethernet USB. Le Pi dispose alors de 2 interfaces ethernet eth0 et eth1 :

pi-bi-eth.jpg

Il n'est pas obligatoire d'avoir deux interfaces réseaux mais cela est plus commode et permet un suivi plus fin du trafic (avec une seule interface, tout ce qui rentre ressort par la même interface et il est dès lors plus délicat de comparer flux entrants et flux sortants puisqu'ils s'annulent au niveau de l'interface unique.

Paramétrage du réseau

Attribuons des paramétrages réseau fixes à eth0 et eth1 dans /etc/dhcpcd.conf comme expliqué ici :

interface eth0
static ip_address=192.168.1.235/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1

interface eth1
static ip_address=192.168.1.234/24

L'interface eth0 est paramétrée avec une IP fixe et utilise comme passerelle de sortie le routeur local (192.168.1.1 dans cet exemple). L'interface eth1 se voit attribuer seulement une adresse IP fixe mais pas de passerelle de sortie. Ainsi, la seule route vers l'extérieur passe au travers d'eth0, ce que nous confirme la commande ip route :

default via 192.168.1.1 dev eth0  metric 202 #La sortie par défaut via eth0, pas de sortie via eth1 !
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.235  metric 202 
192.168.1.0/24 dev eth1  proto kernel  scope link  src 192.168.1.234  metric 203

Il faut maintenant permettre au Raspberry Pi de faire transiter les paquets d'une interface à une autre. Pour ce faire, nous allons activer cette ligne dans /etc/sysctl.conf :

net.ipv4.ip_forward=1

et on ajoutera également ces 3 lignes pour s'assurer que le Raspberry Pi n'enseigne pas aux périphériques autour de lui à le "by-passer" (ce qu'un routeur fait par défaut pour garantir la performance et éviter les noeuds inutiles) :

net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.eth0.send_redirects = 0
net.ipv4.conf.eth1.send_redirects = 0

Pour activer cette configuration, on peut redémarrer ou exécuter :

sysctl -p

Désormais, le Raspberry Pi est capable de faire passer les communications d'eth1 à eth0 mais la route retour ne passe pas nécessairement par le Pi (le routeur n'a aucune raison, lui, de faire transiter le trafic retour vers le Pi s'il peut accéder directement au périphérique final ; évidemment ce cas ne se présente pas si le schéma de câblage fait du Pi le seul lien physique vers la porte de sortie).

Pour forcer la retour par le Pi, on exécutera cette commande iptables :

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Désormais, tout ce qui sort par eth0 voit son adresse source modifiée (filtre MASQUERADE appliquée en POSTROUTING) pour correspondre à l'adresse du Pi : au retour les paquets passeront donc forcément par le Pi qui renverra ensuite vers la bonne destination.

Et sur les périphériques ?

Sur chaque périphérique, il est alors possible d'indiquer comme passerelle l'adresse IP du Pi sur eth1 soit 192.168.1.234 dans cet exemple. Chacun saura comment indiquer à son DHCP local si nécessaire de transporter cette information plutôt que celle par défaut. Dès lors, le Pi devient le point de passage obligé du trafic réseau.

Pour quoi faire ?

Par exemple, nous pouvons maintenant examiner le flux traversant, mesurer le débit avec iftop, couper l'accès à internet à certaines heures, ... On pourra par exemple installer vnstat sur le Pi pour afficher des statistiques d'usage de la bande passante. Les idées ne manquent pas :-)

Passer de letsencrypt-auto à certbot, pas de problème

Let's Encrypt gagne en maturité et voici deux nouvelles importantes :

  • la période bêta est terminée (et avec elle certaines limites d'usage disparaissent)
  • le client letsencrypt-auto devient certbot et bénéficie d'une nouvelle maison
  • et la procédure de renouvellement est désormais beaucoup mieux gérée par le client

Place à certbot!

Si, comme moi, vous utilisiez letsencrypt-auto synchronisé depuis le dépôt Git du client, pas de panique, la transition vers certbot s'effectue sans problème.

D'abord, c'est l'occasion d'utiliser les dépôts Debian qui contiennent désormais certbot. Sur Jessie, pour installer certbot, on utilisera la commande suivante :

apt-get install certbot -t jessie-backports

Et ensuite ? Et bien il n'y a qu'à remplacer les appels vers letsencrypt-auto par des appels vers certbot ! Facile ! A noter que le paquet Debian vient avec un renouvellement automatique paramétré dans /etc/cron.d/certbot, il sera facile de commenter la ligne active si cela ne correspond pas à votre besoin.

Et les renouvellements ?

Comme je l'annonçais en introduction, les renouvellements sont maintenant bien mieux gérés par le client certbot.

La commande

certbot renew

réalisera le renouvellement de tous les certificats qui le nécessitent sur la base des paramétrages contenus dans /etc/letsencrypt/renewal/mon.domaine.tld.conf. On pourra tester le renouvellement sans l'exécuter à l'aide de l'option supplémentaire --dry-run. Enfin, il est possible de paramétrer une action à effectuer avant ou après chaque renouvellement à l'aide des options --pre-hook, --post-hook, --renew-hook. Au moment où j'écris ces lignes, il ne semble pas possible de paramétrer ces options dans les fichiers de renouvellement de configuration mais cela viendra peut-être !

Bons renouvellements !

mercredi 1 juin 2016

Git 2.8+ sur Debian Jessie pour Gitlab 8.5

Si vous hébergez Gitlab sur Debian Jessie, alors la mise à jour de la version 8.4 à la version 8.5 vous aura sans doute demandé une version de Git plus récente que Git 2.1.4 actuellement disponible sur Jessie. Pas de panique : il est possible presque sans effort d'installer une version plus récente de Git depuis les dépôts testing/stretch.

Dans /etc/apt/sources.list, on ajoute ces lignes :

deb http://debian.mirrors.ovh.net/debian/ stretch main
deb-src http://debian.mirrors.ovh.net/debian/ stretch main

deb http://security.debian.org/ stretch/updates main
deb-src http://security.debian.org/ stretch/updates main

Il faut ensuite indiquer à la distribution l'ordre de priorité d'installation en plaçant dans un fichier /etc/apt/preferences.d/mes_priorites (le nom du fichier est tout à fait personnalisable) le contenu suivant :

ackage: *
Pin: release l=Debian-Security
Pin-Priority: 1000

Package: *
Pin: release a=stable
Pin-Priority: 999

Package: *
Pin: release a=testing
Pin-Priority: 50

Package: *
Pin: release a=unstable
Pin-Priority: 50

A ce stade, la commande apt update doit rapatrier les informations de la version testing/stretch mais ne doit pas automatiquement proposer une mise à jour car la priorité donnée à testing (& unstable) est bien moindre que celle donnée à la branche stable.

Pour forcer alors l'installation de la version de Git disponible dans testing/stretch, il faut exécuter :

apt install git/stretch git-man/stretch

dimanche 29 mai 2016

IP statique sur Raspbian Jessie : DHCPCD fait la loi !

Sur Raspbian Jessie, le système n'obéit pas au classique /etc/network/interfaces quand il s'agit de paramétrer le réseau ! Inutile donc de vous escrimer (comme moi) à modifier les paramétrages de ce fichier pour basculer vers une adresse statique au lieu du DHCP par défaut !

En effet, sur Raspbian Jessie, le réseau est paramétré par le service DHCPCD. C'est donc à son niveau qu'il faut agir.

Ainsi, pour attribuer une IP fixe au Pi, ouvrons le fichier /etc/dhcpcd.conf et ajoutons ces lignes à la fin du fichier :

interface eth0
static ip_address=192.168.1.234/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1

dimanche 15 mai 2016

Scripts Munin pour Jirafeau

Si vous utilisez Jirafeau sur votre serveur pour partager des documents, vous serez peut-être contents d'avoir un suivi rapide du nombre de fichiers partagés et du volume total qu'occupent les fichiers de Jirafeau sur votre serveur.

jirafeau_nb-day.png

Rien de plus simple avec Munin !

Créons un premier plugin pour mesurer le nombre de fichiers

Sur la machine porteuse du client (node) Munin, nous allons créer un nouveau script dans le fichier /etc/munin/plugins/jirafeau-nb :

#!/bin/sh
case $1 in
   config)
        cat <<'EOM'
graph_title Jirafeau, number of files
graph_vlabel Nb of files
nbfiles.label Nb of files
EOM
        exit 0;;
esac

printf "nbfiles.value "
echo $(($(find /path/to/jirafeau/var-abcdefghiklmnop/files -type f |wc -l)*1/2))

Il faudra rendre le script exécutable par

chmod a+x /etc/munin/plugins/jirafeau-nb

puis le tester avec munin par

munin-run jirafeau-nb

et enfin redémarrer le client Munin

service munin-node restart

Créons un second plugin pour mesurer l'espace total occupé par les fichiers

On pratique comme au-dessus pour le script dont le contenu est :

#!/bin/sh
case $1 in
   config)
        cat <<'EOM'
graph_title Jirafeau, size of files in Kb
graph_vlabel Size of files in Kb
sizefiles.label Size
EOM
        exit 0;;
esac

printf "sizefiles.value "
du -hsk /path/to/jirafeau/var-abcdefghiklmnop/files |cut -f1

Et hop le tour est joué !

samedi 14 mai 2016

RIP demo.ovh.eu, alternatives open source

Pour partager des fichiers temporairement avec des amis/collaborateurs/proches, j'utilisais fréquemment l'outil demo.ovh.eu. Cet outil avait pour avantage d'être "share & forget" ce qui est idéal pour un document partagé que l'on ne veut pas conserver soi-même.

Malheureusement OVH a décidé d'éteindre demo.ovh.eu et d'inciter les gens à utiliser la plateforme Hubic (qui est très bien mais il est pénible de se connecter et de partager une photo que l'on ne veut pas conserver et qui peut être supprimée quelques jours après le partage).

J'ai donc cherché un outil équivalent Open Source et suis tombé sur Uguu qui répondait à mon cahier des charges mais qui était compliqué à déployer car il contenait tous ses paramètres "en dur" dans le code.

J'ai donc 'forké' Uguu et livre la communauté une version d'Uguu plus facile à déployer et paramétrer : https://github.com/pierre-alain-b/Uguu/

Screenshot_2016-05-14_12-16-35.png

Et d'ailleurs, le mainteneur de la version initiale a accepté le 'Pull request' et a fusionné toutes mes modifications dans l'arbre principal de développement, il est peut-être donc même préférable de se rendre ici : https://github.com/nokonoko/Uguu.

En espérant qu'il puisse rendre service à d'autres !

Et si Uguu ne vous convient pas, il y a aussi :

Merci à François B. pour ces suggestions !

mercredi 13 avril 2016

Imposition libre sous Linux avec PoDoFoImpose

L'imposition en imprimerie n'a rien à voir avec l'imposition fiscale ! Il fallait le rappeler en cette période de déclaration. L'imposition est une étape préparatoire avant impression qui consiste à placer les pages de l'ouvrage à imprimer sur les grandes feuilles qui passeront en presse.

De nombreuses solutions existent sous Linux pour l'imposition comme cela est rappelé sur cette page de la documentation de Scribus : https://wiki.scribus.net/canvas/PDF,_PostScript_and_Imposition_tools.

Je vais présenter ici le fonctionnement de PoDoFoImpose.

Sous Debian, PoDoFoImpose s'installe par

apt install libpodofo-utils

On peut alors appeler la commande :

podofoimpose source.pdf target.pdf plan.plan

où :

  • source.pdf correspond au fichier PDF contenant les pages de l'ouvrage initial
  • target.pdf correspond au fichier PDF à générer
  • plan.plan est une description textuelle du plan d'imposition

Toute l'intelligence se trouve donc dans le fichier plan.plan. Pour commencer à travailler, il suffit de le créer avec l'éditeur texte de son choix et de le débuter par les dimensions du support d'imposition :

$PageWidth=842.4
$PageHeight=597.6

L'unité est le Postscript Point : les dimensions annoncées ci-dessus sont celles d'un A4.

Ensuite, il convient d'ajouter une ligne pour chaque page que l'on souhaite imposer/placer sur le support d'imposition :

source page; target page; rotation; horizontal translation; vertical translation;

Par exemple, ce plan :

1; 1; 0; 0;0;
2; 1; 180; 280.8; 0;
3; 1; 0; 561.6; 0;
4; 2; 0; 0; 0;
5; 2; 180; 280.8; 0;
6; 2; 0; 561.6; 0;
  • place la première page du fichier source sur la première feuille sans changement
  • place la seconde page du fichier source sur la première feuille en effectuant une rotation de 180° et en la décalant horizontalement de 280.8 pts
  • place la troisième page du fichier source sur la première feuille en la décalant horizontalement de 561.6 pts
  • place la quatrième page du fichier source sur la seconde feuille

et ainsi de suite...

Pour des impositions plus compliquées, les valeurs absolues indiquées ici peuvent être remplacées par des expressions numériques (qui seront donc interprétées et calculées par podofoimpose) et il existe un mécanisme de boucle pour éviter la saisie manuelle de l'information si le plan d'imposition est très long ! Les détails sur ces fonctionnalités avancées sont disponibles ici.

Bonne imposition !

lundi 28 mars 2016

LemonLDAP::NG et Let's Encrypt

Nous allons voir dans ce court article comment obtenir des certificats Let's Encrypt pour des services LemonLDAP::NG. Les chemins d'accès évoqués dans la suite correspondent à une installation de LemonLDAP::NG sur Debian Jessie à partir du paquet officiel fourni sur les dépôts de LemonLDAP::NG.

Étape 1 : obtenir un certificat pour le Manager

Nous allons commencer par autoriser l'accès au dossier .well-known dans lequel Let's Encrypt travaille (pour mémoire, il y place une clé qu'un serveur externe vient interroger, permettant ainsi d'affirmer que le demandeur gère le domaine). D'abord dans la configuration d'Apache, dans le fichier /etc/apache2/sites-available/manager-apache2.conf, nous allons remplacer la ligne

RewriteCond "%{REQUEST_FILENAME}" "!^/(?:static|doc|fr-doc|lib).*"

par

RewriteCond "%{REQUEST_FILENAME}" "!^/(?:static|\.well-known|doc|fr-doc|lib).*"

Puis, dans le manager lui-même, il faut demander à LemonLDAP::NG de ne pas bloquer l'accès au même dossier .well-known aux utilisateurs non authentifiés. Ainsi, il faut se rendre dans Virtual Hosts -> manager.mondomaine.fr -> Access rule, et ajouter une nouvelle règle :

  • Regular expression: ^/\.well-known
  • Rule: skip

Screenshot_2016-03-28_06-02-19.png

Dès lors, Let's Encrypt devrait être capable d'accéder à la clé placée dans .well-known. Nous pouvons donc démarrer le processus avec le client Let's Encrypt :

certbot certonly --renew-by-default -a webroot --webroot-path /usr/share/lemonldap-ng/manager/ -d manager.mondomaine.fr

Étape 2 : obtenir un certificat pour le portail d'authentification

Facile :

certbot certonly --renew-by-default -a webroot --webroot-path /var/lib/lemonldap-ng/portal/ -d auth.mondomaine.fr

Étape 3 : obtenir un certificat pour une application placée derrière LemonLDAP::NG

Si l'application est protégée derrière LemonLDAP::NG, il faut commencer par indiquer à LemonLDAP::NG de laisser transiter les requêtes vers le dossier .well-known. A l'image de ce qui a été fait pour le manager, il faut se rendre dans Virtual Hosts -> manager.mondomaine.fr -> Access rule, et ajouter une nouvelle règle :

  • Regular expression: ^/\.well-known
  • Rule: skip

Puis tout simplement (si l'application sous-jacente ne filtre pas les accès à .well-known) :

certbot certonly --renew-by-default -a webroot --webroot-path /var/www/mon-app -d mon-app.mondomaine.fr

dimanche 20 mars 2016

ownCloud/Nextcloud 9 : activer le cache APCu pour améliorer (un peu) les performances

Pour améliorer les performances d'ownCloud/Nextcloud, il est très facile d'activer un memcache facilement en quelques actions seulement :

  • on installe le paquet php5-apcu avec la commande (sous Debian, sinon il faudra adapter le gestionnaire de paquet et le nom du paquet) :
apt install php5-apcu
  • on redémarre Apache :
service apache2 restart
  • on ajoute alors cette ligne dans le fichier de configuration d'ownCloud/Nextcloud :
'memcache.local' => '\OC\Memcache\APCu',

Et le tour est joué !

ownCloud 8.2.2 à ownCloud 9.0 : attention aux applications tierces

La version 9.0 d'ownCloud a été annoncée il y a quelques semaines.

La base

La migration de 8.2.2 vers 9.0 réalisée de manière manuelle se passe très bien pour les applications de base :

  • on fait une sauvegarde de la base de données ownCloud et de l'applicatif 8.2.2
  • on télécharge la dernière version et on la déploie sur l'hébergement
  • on recopie le fichier config.php de l'ancienne version vers la nouvelle version
  • on lance la commande suivante pour mettre à jour la base de données :
sudo -u www-data php occ upgrade

Un seul comportement erroné sur mes installations : le message d'erreur "There were problems with the code integrity check. More information…" s'affiche à cause d'un fichier .htaccess modifié. Il semble que la version 9.0.1 qui doit arriver bientôt corrige ce comportement toutefois non bloquant !

Les applications tierces

En revanche, pour les applications tierces, c'est un peu plus compliqué !

L'application Passwords fonctionne bien à condition d'en télécharger la dernière version : https://apps.owncloud.com/content/show.php/Passwords?content=170480.

Pour Rainloop, il est nécessaire de modifier le fichier owncloud/apps/rainloop/lib/RainLoopHelper.php comme décrit ici : https://github.com/RainLoop/rainloop-webmail/issues/975.

Calendar-plus, Contacts-plus et Tasks-plus ne sont pour le moment pas données pour fonctionner su oC 9. Et il est probable qu'elles ne soient jamais portées pour fonctionner sur oC 9 quand on lit les commentaires ici... méfiance donc !

mercredi 16 mars 2016

Fail2ban pour protéger Samba de Locky

Face à la menace du "ransomware" Locky, j'ai décidé de protéger les données de mon serveur Samba à l'aide de Fail2ban. L'idée est simple : si des mouvements pouvant correspondre à une action de Locky sont détectés, alors l'IP à l'origine de l'action est bannie du serveur Samba.

Étape 1 : activer l'audit dans Samba

Samba dispose de puissantes fonctions d'audit qui permettent de garder trace de toutes les opérations sur un partage. Elles s'activent à l'aide des options full_audit dans le fichier /etc/samba/smb.conf. Attention toutefois à la volumétrie que cela peut représenter : si le serveur Samba est très sollicité, la taille des logs sera fort importante (surtout si l'on suit l'événement "open" qui est déclenché régulièrement lors de toute navigation sur le partage Samba) !

Plaçons donc le paramétrage suivante dans la section "Global" du fichier de configuration de Samba (/etc/samba/smb.conf par défaut) :

full_audit:priority = notice
full_audit:facility = local5
full_audit:success = mkdir rmdir rename unlink open
full_audit:prefix = %u|%I|%S

puis redémarrons Samba :

service samba restart

et voilà le fichier /var/log/samba/audit.log qui se remplit et recense tous les mouvements sur le serveur Samba. Une bonne rotation des logs sera nécessaire pour ne pas se faire piéger ! Attention également à la petite perte de performance que cette écriture régulière demandera.

Étape 2 : paramétrer le nouveau filtre d'exclusion pour Fail2ban

Nous allons demander à Fail2ban de bannir tout ordinateur qui effectuerait une opération sur fichier *.locky ou *.xxx sur le serveur. On crée le fichier /etc/fail2ban/filter.d/antilocky.conf suivant :

[Definition]
failregex = \|<HOST>\|NomDePartage\|.*\|ok\|.*\.(locky|xxx|mp3)

ignoreregex =

en remplaçant "NomDePartage" par le nom du partage Samba concerné.

Étape 3 : paramétrer une nouvelle prison dans Fail2ban

On paramètre comme il se doit Fail2ban dans /etc/fail2ban/jail.local en ajoutant notamment la section suivante :

[antilocky]
enabled = true
filter  = antilocky
backend = auto
logpath = /var/log/samba/audit.log
maxretry  = 2
banaction = iptables-allports
port = all

On peut alors redémarrer Fail2ban par :

service fail2ban restart

et vérifier dans les logs /var/log/fail2ban.log que la nouvelle prison se charge correctement.

Et voilà Fail2ban prêt à bannir tout ordinateur qui se connecterait au serveur Samba en manipulant des fichiers *.locky ou *.xxx. Evidemment il peut y avoir des faux positifs. Il est donc recommandé d'être vigilant et d'activer peut-être la notification par courriel des bannissements de ce type pour être en mesure de débannir dans le cas d'un faux positif et d'intervenir sur le poste infecté s'il s'avère qu'une réelle infection est en cours.

Étape 4 : limitations

La principale limitation est l'usage de l'extension de nom de fichier comme critère de signalement. Si des variantes du virus adoptent d'autres extensions (par exemple .pdf) alors il ne sera plus possible de détecter l'action frauduleuse de la sorte. On pourra éventuellement suivre le nombre d'opérations sur le partage Samba et alerter l'administrateur lorsque de trop nombreuses opérations de suppression sont en cours...

jeudi 25 février 2016

ownCloud 8.2.2 : pas de défilement sur les partages publics de photos

Si vous utilisez ownCloud 8.2.2, vous aurez peut-être constaté qu'il n'est plus possible de se déplacer vers le bas (défilement vers le bas, "scroll" pour les amateurs de termes anglais) sur les partages publics de photos...

Ce dysfonctionnement a été rapporté à plusieurs reprises notamment ici et encore ici. Il sera corrigé dans la version 8.2.3 à paraître et la solution facile en attendant est de désactiver l'application PDFViewer d'ownCloud :

Screenshot_2016-02-25_08-02-36.png

Pour les plus courageux, il est également possible de mettre à jour uniquement l'application PDFViewer à partir du code disponible ici https://github.com/owncloud/files_pdfviewer.

dimanche 7 février 2016

Transformer une découpeuse laser avec Arduino et Grbl

De nombreuses découpeuses laser sont disponibles sur AliExpress (plateforme de vente chinoise) à des tarifs défiant toute concurrence. L'usage d'une découpeuse laser était d'ailleurs présentée dans le numéro de décembre de Linux Pratique (page 24, "Réalisez des gravures laser à l'aide d'Inkscape").

flowRoot4158.jpg

Attention ! Une découpeuse laser est un outil dangereux : les lasers utilisés sont très puissants et provoqueraient la cécité totale de toute personne qui regarderait le faisceau même brièvement. Équipez-vous de lunettes avec un abattement optique suffisant dans la longueur d'onde de travail et ne regardez jamais le faisceau même équipé. Méfiez-vous également des réflexions lumineuses scélérates ! Enfin, les matérieux découpés peuvent s'enflammer sous l'action du laser. L'usage d'une découpeuse laser nécessite une attention constante !

La découpeuse laser sur laquelle je mettais la main dernièrement avait un défaut majeur : elle n'était contrôlable qu'à l'aide de deux binaires chinois impossibles à exécuter sous Linux et à la qualité médiocre... Qu'à cela ne tienne : conservons le matériel mais remplaçons l'intelligence par un Arduino équipe de Grbl.

À propos de Grbl

Grbl (https://github.com/grbl/grbl) est un micrologiciel libre développé sur Arduino pour contrôler des graveuses CNC (Computer Numerical Control), i.e. des fraiseuses munis d'une tête mobile contrôlée en X, Y et Z par un ordinateur. Grbl interprète du G-code (cf. plus bas) et déplace en conséquence un outil sur 3 axes (X, Y et Z) et contrôle la puissance de cet outil. Il comprend de multiples optimisations sur l'usage et le déplacement des moteurs afin de gérer correctement les accélérations, les trajectoires...

Dans le cas de notre laser, nous n'aurons pas d'axe Z et nous nous contenterons d'utiliser Grbl pour contrôler X, Y et la puissance du laser (que l'on contrôlera comme la vitesse de rotation d'une fraise).

À propos de G-code

Le G-code est un langage de programmation inventé dans les années 1950 pour le contrôle des machines CNC. Il comprend un certain nombre d'instructions pour le contrôle d'équipements, par exemple :

G21 (définit l'unité de travail comme étant le millimètre)
M5 (éteint l'outil : la fraise, le laser)
F400 (choisit une vitesse de déplacement de 400 mm/min)
S500 (définit la puissance de l'outil : 500 RPM pour la fraise)

G00 X5 Y5 Z5 (déplacer l'outil vers [x,y,z] = [5,5,5] en laissant la machine choisir le chemin)
G01 X10 Y10 (déplacer l'outil vers [x,y] = [10,10] en effectuant une ligne droite, on ne change pas Z)
G02 X20 Y10 I5 J0 (effectuer un arc de cercle de centre [x,y] = [15,10] jusqu'au point [x,y] = [20,10])
M3 (démarre l'outil à la puissance sélectionnée auparavant i.e. S500)
...
M5 (éteint l'outil)

Il est à noter que Grbl ne supporte pas toutes les instructions du G-code (il y a des commandes exotiques qui n'ont pas un intérêt sensationnel et qui alourdiraient le code chargé sur Arduino) mais les principales sont bien gérées.

Mise en pratique

On supprime donc l'électronique chinoise embarquée initialement et on la remplace par un Arduino couplé à deux easydrivers pour contrôler les moteurs (stepper motors) contrôlant les axes X et Y ainsi que le laser. Le laser est contrôlé par 3 fils : une alimentation, une masse et un fil de contrôle par modulation TTL i.e. envoi d'un signal carré avec une fréquence de plus en plus élevée (jusqu'à 10 kHz) qui commande la puissance.

Le circuit ressemble alors à ceci : laser_sketch.png

On peut alors charger le micrologiciel Grbl sur l'Arduino comme décrit ici. Si on se connecte en série à l'Arduino (avec un baud rate à 115 200), on doit alors voir à l'allumage :

Grbl 0.9j ['$' for help]

Grbl (version 0.9j) est prêt à recevoir nos commandes !

On peut alors lancer les commandes de son choix dans le port série pour interagir avec Grbl et contrôler la découpeuse laser.

Pour plus d'aisance, on pourra installer un logiciel de contrôle tel que UniversalGcodeSender disponible ici.

Screenshot_2016-02-07_05-57-43.png

La machine est désormais prête à recevoir des instructions en G-code. Il ne reste plus qu'à utiliser la méthode de son choix pour générer les G-codes de ses créations.

Générer des G-codes avec Inkscape

Il existe des extensions pour générer les G-codes à partir de chemins vectoriels dans Inkscape. L'extension de base est même installée par défaut dans Inkscape :

Screenshot_2016-02-07_06-05-01.jpg

On pourra se référer à ces documentations pour l'utiliser, éventuellement en adaptant quelque peu au cas du laser pour lequel l'axe Z ne compte pas et les vitesses peuvent être plus élevées :

Quelques ordres de grandeur

Avec un laser de 5.5W à la longueur d'onde de 450 nm (laser bleu) :

  • on dessine joliment sur du carton brun à F400 / S600
  • on découpe 1 mm de bois avec F200 / S1000 en repassant 4 fois sur le trait
  • on grave le bois clair avec F200 / S1000 et un seul passage

Bonne gravure et bon découpage laser !

samedi 6 février 2016

ino pour Arduino : compiler, envoyer et écouter en série sans l'IDE Arduino

L'Arduino IDE est super pour débuter. Mais rapidement, on peut se sentir un peu à l'étroit dans l'outil. Je l'ai donc avantageusement remplacé par mon éditeur de texte habituel (Atom) et "ino" (http://inotool.org/) pour communiquer avec les planches Arduino.

Installer ino

ino s'installe facilement sur une machine munie de Python2.7 par :

pip install ino

ou alors en récupérant les sources d'ino ici.

Il faut également installer l'IDE Arduino et picocom pour la communication sur le port série - sur Debian Jessie on pourra l'installer ainsi :

apt install arduino picocom

Utiliser ino

Avant toute chose, on crée un nouveau projet :

mkdir mon_projet
cd mon_projet
ino init

On place alors le code de son choix dans le fichier 'sketch.ino' placé dans le dossier 'src'.

Pour compiler :

ino build

Pour envoyer sur l'Arduino :

ino upload

Et pour écouter sur le port série :

ino serial

Pour aller plus loin

On pourra lancer :

ino --help

ou aller lire ici : http://inotool.org/quickstart

Constuire un photomètre avec Arduino

Nous allons expliquer ici comment fabriquer un photomètre avec la plateforme Arduino et le composant BH1750 (encore appelé GY-30, fiche technique ici) que l'on trouve pour quelques euros chez les bons revendeurs électroniques.

Un photomètre qui parle en série

Une première version du photomètre sera simple : nous utiliserons les facultés d'Arduino à communiquer via un port série pour afficher le niveau de luminosité mesuré. Le circuit est alors assez simple (cf. représentation ci-dessous) :

  • le pin VCC du capteur se connecte au pin 5V de l'Arduino
  • le pin GND du capteur se connecte au pin GND de l'Arduino
  • le pin SDA du capteur se connecte au pin A4 (Analogique 4) de l'Arduino
  • le pin SDL du capteur se connecte au pin A5 (Analogique 5) de l'Arduino

Uno_et_BH1750.png

On compile alors le code suivant et on le charge sur l'Arduino (par exemple avec l'IDE Arduino) :

#include <Wire.h>
 
int BH1750_address = 0x23; // i2c Addresse
byte buff[2];
 
void setup() {
  
  Wire.begin();
  BH1750_Init(BH1750_address);
  
  delay(200);
  Serial.begin(9600);
  Serial.println("Démarrage du système... patientez svp !");
}
 
void loop() {
  
  float valf=0;
 
  if(BH1750_Read(BH1750_address)==2){
    valf=((buff[0]<<8)|buff[1])/1.2;
  
    if(valf<0) {
      Serial.print("> 65535");
    }
    else {
      Serial.print((int)valf,DEC);
    }
    Serial.println(" lx"); 
  }
  delay(1000);
}
 
void BH1750_Init(int address) {
  Wire.beginTransmission(address);
  Wire.write(0x10); // 1 [lux] aufloesung
  Wire.endTransmission();
}
 
byte BH1750_Read(int address) {
  byte i=0;
  Wire.beginTransmission(address);
  Wire.requestFrom(address, 2);
  while(Wire.available()) {
    buff[i] = Wire.read(); 
    i++;
  }
  Wire.endTransmission();  
  return i;
}

Et hop, sur le port série, on peut voir :

Démarrage du système... patientez svp !
92 lx
92 lx
92 lx
75 lx
47 lx
342 lx
43 lx

Un photomètre avec son propre écran LCD

Rajoutons un écran LCD pour afficher le résultat sans avoir à ouvrir un port série ! Nous allons donc brancher un LCD Keypad Shield (tel qu'ici) sur l'Arduino, et nous allons modifier le code comme suit :

#include <Wire.h>
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int BH1750_address = 0x23; // i2c Addresse
byte buff[2];

void setup() {

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Look the world");

  Wire.begin();
  BH1750_Init(BH1750_address);

  delay(200);
  Serial.begin(9600);
}

void loop(){
  float valf=0;
  if(BH1750_Read(BH1750_address)==2) {
    valf=((buff[0]<<8)|buff[1])/1.2;
    if(valf<0) {lcd.setCursor(0,0); lcd.print("> 65535 lx");}
    else {lcd.setCursor(0,0); lcd.print((int)valf,DEC); lcd.print(" lx                    ");}
  }
  else {
    lcd.setCursor(0,0); lcd.print("Error...             "+BH1750_Read(BH1750_address));
  }
  delay(1000);
}

void BH1750_Init(int address) {
  Wire.beginTransmission(address);
  Wire.write(0x10); // 1 [lux] aufloesung
  Wire.endTransmission();
}

byte BH1750_Read(int address){
  byte i=0;
  Wire.beginTransmission(address);
  Wire.requestFrom(address, 2);
  while(Wire.available()){
    buff[i] = Wire.read();
    i++;
  }
  Wire.endTransmission();
  return i;
}

On compile et on charge sur l'Arduino, et hop le tour est joué !

photometre.jpg

jeudi 4 février 2016

OpenSSL : détecter la péremption d'un certificat avec l'option -checkend

Dans un précédent article (ici), je proposais une méthode pour renouveler les certificats Letsencrypt en l'absence d'un mécanisme officiel pour le moment. Dans cette méthode (enfin ce script), je vérifiais la date du certificat avec "date -r", extrapolant la date de fin de validité à l'aide de la date de création du certificat et de la connaissance de la durée de validité par défaut des certificats de Letsencrypt.

Il y a en fait beaucoup plus intelligent ! Merci à mon beau-frère pour cette idée (toujours écouter au moins d'une oreille son beau-frère !)

Le manuel d'OpenSSL nous apprend l'existence de l'option suivante :

-checkend arg
checks if the certificate expires within the next arg seconds and exits non-zero if yes it will expire or zero if not.

Dès lors, il est facile de détecter si un certificat périme dans les 30 jours (2 592 000 secondes) :

if openssl x509 -checkend 2592000 -noout -in file.pem
then
  echo "Certificat valide encore au moins 30 jours"
else
  echo "Certificat périmant dans les 30 jours... à renouveler !"
fi

lundi 1 février 2016

Letsencrypt : renouveler intelligemment malgré les limites de la bêta

Depuis Mai 2016, le service Let's Encrypt n'est plus en bêta et les limitations de la bêta évoquées ici ne sont plus mordantes !

Depuis Mai 2016, le client letsencrypt est devenu certbot (https://certbot.eff.org/) ! les commandes évoquées plus bas sont sans doute valables en remplaçant letsencrypt-auto par certbot ! Il faut aussi noter que le client certbot dispose désormais de fonctions de renouvellement plus élaborées qu'auparavant ! Cet article est conservé pour archive et inspiration.

Letsencrypt se présente comme le futur du chiffrement sur internet. Bien que déjà fonctionnel, le service offert est encore en phase de test (bêta) et par conséquent certaines contraintes s'appliquent aux usagers testeurs. Parmi ces contraintes, les 2 les plus bloquantes sont :

  • pas de système de renouvellement automatique pour le moment (c'est prévu, vivement !)
  • limite imposée de 5 certificats par domaine par semaine (i.e. qu'il faut attendre une semaine pour pouvoir créer des certificats pour un nouveau sous-domaine d'un domaine qui possède déjà 5 certificats de sous-domaine)

Pour Letsencrypt qui émet des certificats à la validité courte de 3 mois, le renouvellement doit être fait régulièrement et il correspond ni plus ni moins à l'édition d'un nouveau certificat.

La contrainte évoquée plus haut est bloquante pour le renouvellement : en effet il n'est pas possible de renouveler plus de 5 certificats par semaine pour un même domaine...

Principe du renouvellement à terme

A terme, un système de renouvellement automatique sera intégré à Letsencrypt et il suffira de lancer tous les 2 mois (par exemple via cron) la commande demandant le renouvellement de tous les certificats en approche de péremption. Vivement cela !

Une méthode fonctionnelle aujourd'hui

Aujourd'hui, à nous de créer l'automatisme qui va bien et qui permettra aussi de contourner la limite des 5 renouvellements par semaine (en réalisant un roulement). Nous allons détailler ici un script qui, appelé chaque semaine, :

  • détecte les certificats qui ont moins de 30 jours de validité (2592000 secondes)
  • demande le renouvellement de chaque certificat dans ce cas

Voici le code du script :

#!/bin/bash
declare -a list=(
"/etc/letsencrypt/live/domaine1.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/domaine1/website -d domaine1.tld -d www.domaine1.tld"
"/etc/letsencrypt/live/sous.domaine1.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/sous/domaine1/website -d sous.domaine1.tld -d www.sous.domaine1.tld"
"/etc/letsencrypt/live/domaine2.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/domaine2/website -d domaine2.tld -d www.domaine2.tld"
)

for line in "${list[@]}"
do
	IFS=";" read -ra stuff <<< $line
	folder=${stuff[0]}
	command=${stuff[1]}
        if openssl x509 -checkend 2592000 -noout -in $folder/fullchain.pem
        then
                echo "Nothing to do for $folder"
        else
                $command
                rm -f $folder/total.pem
                cat $folder/fullchain.pem $folder/privkey.pem > $folder/total.pem
                echo "Done for $folder"
        fi
done

Rapidement :

  • on commence par lister dans un tableau chaque domaine dont il faut s'occuper (en indiquant le chemin correspondant à ce domaine dans le dossier /etc/letsencrypt/live/) et, séparée par ";", la commande Letsencrypt utilisée pour le renouvellement. Il s'agit de la même commande que pour la création initiale du certificat sauf que l'on ajoute l'option "--renew-by-default"
  • on parcourt ensuite le tableau élément par élément :
    • en vérifiant l'âge du certificat (avec openssl)
    • en lançant la commande de renouvellement s'il est trop proche de la péremption

Si l'on utilise Letsencrypt avec Pound, on ajoutera 2 actions :

  • remplacer le fichier .pem utilisé par Pound par la nouvelle version obtenue
  • redémarrer Pound

Le script devient alors :

#!/bin/bash
declare -a list=(
"/etc/letsencrypt/live/domaine1.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/domaine1/website -d domaine1.tld -d www.domaine1.tld"
"/etc/letsencrypt/live/sous.domaine1.tld;certbot --renew-by-default -a webroot --webroot-path /path/to/sous/domaine1/website -d sous.domaine1.tld -d www.sous.domaine1.tld"
"/etc/letsencrypt/live/domaine2.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/domaine2/website -d domaine2.tld -d www.domaine2.tld"
)

for line in "${list[@]}"
do
	IFS=";" read -ra stuff <<< $line
	folder=${stuff[0]}
	command=${stuff[1]}
        if openssl x509 -checkend 2592000 -noout -in $folder/fullchain.pem
        then
                echo "Nothing to do for $folder"
        else
                $command
                rm -f $folder/total.pem
                cat $folder/fullchain.pem $folder/privkey.pem > $folder/total.pem
                echo "Done for $folder"
        fi
done
service pound restart

Archive

Dans une ancienne version de ce billet, on utilisait le morceau de script suivant se basant sur la date de dernière modification du fichier de certificat plutôt que d'utiliser openssl, mais c'est moins propre. Pour archivage, voici le test qui était alors utilisé (renouvellement des certificats plus vieux que 60 jours) :

	timesincelastchange=$(expr $(expr $(date +%s) - $(date +%s -r $folder/fullchain.pem )) / 86400)
	if [ $timesincelastchange -gt 60 ]
	then
		$command
		echo "Done for $folder"
	else
		echo "Nothing to do for $folder"
	fi

- page 2 de 6 -