Thursday, 26 April 2018
|
Écrit par
Grégory Soutadé

La toute récente sortie de Pannous a été l'occasion de créer un nouveau sous-domaine pour héberger le service. Service qui comporte une partie d'authentification, donc obligation de passer par une communication sécurisée (SSL/TLS). Autrefois, la chose était plus aisée, puisque je pouvais générer mes propres certificats et notamment des certificats "wildcards", donc valides pour tous les sous-domaines.

Sauf que je suis passé à Let's Encrypt. Il a donc fallu attendre la sortie de la version 2 du protocole (qui a eu du retard) afin de bénéficier de cette fonctionnalité. Surtout, qu'au passage, le paquet Debian (backport) de certbot a été cassé, ce qui m'a forcé à revenir à une version encore plus ancienne.

Bref, les choses sont maintenants stables et déployées sur les serveurs respectifs. Petit problème néanmoins, la génération d'un certificat wildcard par Let's Encrypt requiert l'ajout d'une entrée DNS (comme challenge). Fatalité, le DNS de Gandi a lui aussi évolué pour passer en version 5. Avec pour principal avantage une mise à jour immédiate des entrées DNS (là où il fallait plusieurs minutes/heures auparavant). Autre nouveauté : l'API Gandi change de format. On oublie l'ancien XML-RPC (ce qui était pratique avec des bindings Python déjà tout faits), pour passer au REST (un peu moins formel).

Mélangeons tout ça pour obtenir un joli cocktail, dont la recette nous est donnée par Sébastien Blaisot qui, pour nous simplifier la vie, a créé des scripts de génération de certificats wildcards via Let's Encrypt. Le code est disponible sur GitHub et supporte le logiciel bind (en local), l'API OVH et la nouvelle API Gandi. Il ne reste plus qu'à cloner le dépôt et lancer la commande magique :

cd certbot-dns-01-authenticators/gandi-livedns
certbot certonly --manual --server https://acme-v02.api.letsencrypt.org/directory\
 --manual-auth-hook $PWD/auth.py --manual-cleanup-hook $PWD/cleanup.py -d '*.soutade.fr'

Et voilà un joli certificat tout frais !

Du coup, je me suis grandement inspiré de son code pour mettre à jour mon script de DNS fallback (serveur de secours via redirection DNS). Avec, en prime, un passage en Python 3 ! À terme, il faudra que j'ajoute le support IPv6.

#!/usr/bin/env python3
# -*- encoding: utf-8 -*-

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import requests
import json
import re

# Config
domain="soutade.fr"
API_KEY = "YOUR-KEY"
livedns_api = "https://dns.api.gandi.net/api/v5/"
dyndns_url = 'http://checkip.dyndns.com/'
headers = {
    'X-Api-Key': API_KEY,
}
A_RECORD_NAME="@" # Record of A type

# Get current IP
current_ip = ''
response = requests.get(dyndns_url)
if response.ok:
    pattern = re.compile('[^:]*(\d+\.\d+\.\d+\.\d+)')
    result = pattern.search(response.text, 0)
    if result == None:
        print("No IP found")
        exit(1) 
    else:
        current_ip = result.group(0).strip()
else:
    print("Connexion error")
    response.raise_for_status()
    exit(1)

print('Your Current IP is %s' % (current_ip))

# Retrieve domains address
response = requests.get(livedns_api + "domains", headers=headers)

if (response.ok):
    domains = response.json()
else:
    response.raise_for_status()
    exit(1)

domain_index = next((index for (index, d) in enumerate(domains) if d["fqdn"] == domain), None)

if domain_index == None:
    # domain not found
    print("The requested domain " + certbot_domain + " was not found in this gandi account")
    exit(1)

domain_records_href = domains[domain_index]["domain_records_href"]

# Get recorded IP
response = requests.get(domain_records_href + "/" + A_RECORD_NAME + "/A", headers=headers)

if (response.ok):
    record = response.json()
else:
    print("Failed to look for recorded IP")
    response.raise_for_status()
    exit(1)

print('Old IP : %s' % (record['rrset_values'][0]))

if current_ip != record['rrset_values'][0]:
    record['rrset_values'][0] = current_ip

    # Put updated IP
    response = requests.put(domain_records_href + "/" + A_RECORD_NAME + "/A", headers=headers, json=record)

    if (response.ok):
        print("IP updated")
    else:
        print("something went wrong")
        response.raise_for_status()
        exit(1)

    exit(34) # IP updated return !!

exit(0)

Une version téléchargable est disponible ici.

Thursday, 26 April 2018
|
Écrit par
Grégory Soutadé

Logo Pannous

Il y a quelques temps déjà, Mozilla a décidé d'abandonner son format et ses API pour les extensions de son navigateur (Firefox) afin de tout migrer vers les WebExtensions. Ces dernières reprennent en très grande partie les caractéristiques de son concurrent Chrome. Cet événement, à priori négatif, m'a permis d'améliorer la sécurité de mon extension gPass et de factoriser grandement le code. Malheureusement, la migration de la version 0.7 (ancien format) à la version 0.8 n'est pas automatique (contrairement à Chrome) et beaucoup d'utilisateurs se sont perdus en chemin. C'est à ce moment-là que je me suis rendu compte qu'il me manquait un lien avec les utilisateurs de manière générale.

Il est vrai que ma forge inDefero n'est plus maintenue depuis maintenant 8 ans, qu'il n'y a pas de fonctionnalité "sociale" ou de "distribution" pour prévenir d'éventuelles nouveautés. Pour autant, je n'ai pas envie de passer sur une autre plateforme (notamment Github) et je ne trouve aucun remplaçant aussi ergonomique. La plupart des candidats ne se contentant que d'imiter la plateforme propriétaire majeure. L'idée, toute simple, est donc de créer des listes de diffusion projets (mailing list ou announce list).

La référence dans le domaine est GNU mailman. Je pourrais y faire les mêmes reproches que pour les forges : compliqué à configurer, moche, lourd. Alors que mes besoins sont assez légers. Du coup, je me suis lancé dans l'écriture d'un petit moteur de liste de diffusion. À priori, rien de compliqué : un petit script pour la gestion des mails et une gestion assez simples des listes/groupes/utilisateurs (ajout, modification, suppressions, droits). Le tout en PHP : simple, rapide et avec tous les modules nécessaires. En effet, j'ai décidé d'abandonner mon Django favoris, car, s'il aurait pu répondre à tous mes besoins, il est extrêmement lent pour mon petit serveur.

Au début, j'ai récupéré un peu de code d'un ancien projet avec un framework perso (simpliste). Mais en complexifiant un tout petit peu le projet, je me suis dit qu'il était inutile de ré inventer la roue. J'ai donc fait le tour des frameworks PHP (des plus lourds et connus aux plus légers). C'est assez impressionnant de voir que certains font des centaines de méga pour une application de moins de 2MO... Après comparaison, il s'avère qu'ils adoptent tous la même philosophie HMVC et l'on peut passer de l'un à l'autre assez rapidement. Après avoir longtemps lorgné sur CakePHP, j'ai finalement décidé de me lancer en FuelPHP. J'y retrouve toutes les fonctionnalités que j'attends, en plus d'être léger et rapide.

Bref, tout ça pour annoncer la création de Pannous pour PHP Annoucement System. L'objectif est d'être simple à installer, configurer, utiliser. On y retrouve deux fonctionnalités inédites :

  • Plusieurs niveaux de droits pour l'émission d'un mail sur la liste (écrivains, lecteurs, utilisateurs, tout le monde), avec la possibilité de vérifier la signature GPG.
  • API Rest pour l'inscription/désinscription d'une liste (avec génération automatique de code HTML/AJAX).

Pour le reste, c'est du classique : gestion des utilisateurs, des groupes, des listes, inscription/désinscription en ligne ou par mail...

Le projet est disponible sur ma Forge sous licence GPL v3.

Naturellement, j'ai créé une liste pour Pannous : pannous-announce@soutade.fr

Friday, 09 March 2018
|
Écrit par
Grégory Soutadé

Logo du T-Shirt Propre

Comme chaque année et, sauf pour ceux qui veulent profiter de leurs vacances en altitude, l'hiver est une période que l'on aime bien retrouver (la neige, le chocolat chaud au coin du feu...), mais que l'on apprécie encore plus quand elle se termine. Il est donc temps de penser printemps, soleil, balades en extérieur... Bref, c'est bientôt le retour de la saison du t-shirt !

Car, si pour les femmes la mode propose une quantité considérable de tenues, les hommes sont bien moins lotis et le t-shirt apparaît comme l'élément de base le plus couramment utilisé. D'autant plus que son prix est relativement faible (5€-15€), qu'il possède de multiples motifs et couleurs, pratique, léger, suffisant. D'ailleurs, est-on prêt à payer plus cher ce pauvre bout de tissu ? Plus encore quand on sait qu'il a une durée de vie moyenne assez faible (surtout quand la mode passe par là).

Le sujet étant lui aussi tendance, une question m'est passée par la tête : "Est-ce qu'il existe des t-shirts fabriqués en France ?". Le marché semble décoller puisqu'il en existe plusieurs (liste non exhaustive) :

Il faut bien lire les petites lignes. Parfois, ils ne sont que partiellement transformés (teinture, impression, logo), ou déssinés en France... Les prix varient de 25€ à plus de 50€. Sachant que, hors promotion, un t-shirt de marque (style Chevignon) démarre à 30€. Hors, l'industrie textile est connue pour ses marges pharaoniques : x10, x100. Pour autant, certains fabricants sus-cités profitent de la vague "fabriqué en France" pour gonfler les prix de manière abusive (Goudron Blanc par exemple, alors que les t-shirts sont fabriqués au Portugal...).

Hasard du calendrier, Le samedi 10 février 2018, France 2 diffuse un reportage de l'émission "Tout compte fait", sur "La face cachée des petits prix dans la mode". Le format long de ce genre d'émission permet d'avoir un argumentaire assez étayé, même s'il en reste parfois un peu partisan. Quoi qu'il en soit, il met en exergue les problèmes liés à l'industrie textile globalisée.

Tout d'abord le coton. Cette fibre végétale est la plus utilisée pour la confection de vêtements. Les rendements ont été démultipliés durant le 18e siècle avec la révolution industrielle, mais l'on a retrouvé des traces datant de plusieurs milliers d'années. Un climat (sub-)tropical avec une alternance de saison humide puis sèche est nécessaire pour qu'elle s'épanouisse. On en produit environ 25 millions de tonnes par an. C'est la composante principale des t-shirts, mais aussi des jeans et de bien d'autres vêtements. La teinture ensuite. Naturellement, le coton est blanc, il est ensuite filé puis teint. Finalement, le transport des matières premières.

À priori, il n'y a rien de bien méchants dans ces éléments. Surtout que l'on utilise une fibre naturelle (donc renouvelable). C'est sans compter sur la partie sombre de l'économie de marché et des processus industriels. Dans ce petit jeu où la croissance est un élément "vital", il faut (parfois) créer le besoin, y répondre tout en réduisant les coûts de production et en maximisant les marges. La première partie est régie par le génie marketing et financier, la seconde par une logique plus industrielle. Logique qui s'appuie sur un rapport de force déséquilibré afin d'obtenir son produit/sa matière première au prix le plus faible. Le prix est le seul facteur, il n'y a pas d'éthique dans ce système. Pour (sur)vivre et assurer la subsistance de sa famille (puisque c'est la seule chose qui compte), le soumis n'aura pas forcément plus d'état d'âme à réaliser un travail au détriment de son propre environnement et de celui des générations futures. Particulièrement quand on ne lui laisse entrevoir aucune alternative à ce qu'il réalise et peut réaliser quotidiennement.

Ainsi, les conditions de fabrication de ces quelques bouts de tissus sont souvent catastrophiques. On utilise des techniques du début du siècle dans des pays où le coût de la main d'œuvre est faible et où les réglementations (ou du moins les contrôles) sont quasi inexistants. Le tout pour répondre à une demande croissante, sans vision globale, sans vision sur le long terme, car l'Économie prime avant tout. Les problèmes qui en découlent sont classiques : assèchement des régions à cause de l'irrigation intensive, épandage massif de pesticides volatiles, non traitement des polluants issus des teintures qui se retrouveront dans les nappes phréatiques...

Un t-shirt bio, c'est ridicule ! C'est ridicule car on associe le terme "bio" au domaine alimentaire. En ce qui concerne le textile, il s'agira d'avoir une empreinte réduite sur l'environnement : peu ou pas de pesticides, traitement des polluants... Pour autant, il ne faut pas considérer un produit "bio" comme le graal. Ces derniers ont quand même un impact écologique non nul, surtout quand on prend en compte ce qui entoure le produit (emballages & co) et son transport. Typiquement, celui qui a bonne conscience en achetant du miel bio Carrefour se trompe : il s'agit d'un mélange de miels, certes bios, mais provenant d'Union Européenne et d'Amérique Latine, le tout conditionné en Belgique et vendu en France. Alors qu'il existe des miels locaux d'excellente qualité à un prix équivalent.

C'est dans ce contexte global que l'on comprend les raisons de la marque "T-Shirt propre". Si l'objectif, ou la prétention, des fondateurs est clair, je trouve l'aspect marketing d'un tel nom très mauvais car il nous vient immédiatement à l'esprit son antagoniste, "sale", ce qui ne donne pas envie d'acheter. Bref, cette PME de l'Aude ne s'appuie que sur des partenaires Français afin de proposer des produits de qualité, éco responsables. Le coton, bio, est importé de Grèce car il n'est pas possible (pour le moment) de le faire pousser en France. C'est donc le retour de l'industrie textile dans le sud-ouest ! Région autrefois spécialisée (entre autres) dans ce domaine, même si à l'époque on utilisait de la laine de mouton. La marque propose une ligne femme et homme, sobres (on aime ou on n'aime pas), à des prix raisonnables (33€ le pack de 3 ou 39€ l'un) pour des produits entièrement réalisés en France ! Pour avoir acheté un pack, je ne peux que les recommander chaudement. Le t-shirt est assez épais (ce qui tranche avec les versions plus bas de gamme), les coutures sont renforcées.

Monday, 08 January 2018
|
Écrit par
Grégory Soutadé

Logo Let's encrypt

Au revoir 2017, bonjour 2018 ! Alors que l'actualité brûlante du moment tourne autour de la faille de sécurité trouvées sur différents processeurs supportant l'exécution spéculative (faille non triviale à exploiter), j'ai pour ma part choisi de passer à Let's Encrypt. Il s'agit d'une organisation à but non lucratif dont l'objectif est de promouvoir l'utilisation de connexions sécurisées (SSL/TLS) sur internet. Pour ce faire, elle propose la génération gratuite (et scriptée) de certificats pour le protocole HTTPS. Elle trouve de plus en plus les faveurs des webmasters, surtout quand on sait qu'un certificat coûte entre 15€ et plusieurs milliers d'euros par an (avec des garanties, tout ça, tout ça).

Leurs certificats sont déployés depuis plus de deux ans maintenant et il faut dire que ça marche plutôt bien ! Auparavant, j'utilisais ma propre autorité de certification, ce qui permet de contrôler finement les paramètres du certificat final, vérifier que l'on n'est pas attaqué... Mais il faut reconnaître que pour la navigation courante et surtout pour gPass, avoir un certificat reconnu de base est devenu une nécessitée.

Surtout que let's encrypt fourni l'utilitaire certbot (disponible dans les paquets Debian) qui s'occupe de (re-)générer, valider, configurer automatiquement tout ce qu'il faut. Il n'y a qu'à renseigner une adresse mail valide ainsi que la liste des domaines concernés.

J'ai eu deux erreurs lors de cette procédure. La première :

Domain: denote.soutade.fr
Type:   unauthorized
Detail: Incorrect validation certificate for tls-sni-01 challenge.
Requested
605840d8f5902f3f5f9b465e90fefda9.5e9055daac5e4439a0d768344e093378.acme.invalid
from 89.95.86.199:443. Received 1 certificate(s), first certificate
had names
"58d2ce91621ca3bc9dad2ae778ba8110.6f005c32f7a4345e14b2120f34d7e6c7.acme.invalid,
dummy"

Et la seconde concernant le nom de domaine teamazurevasion.fr que j'héberge également sur le même serveur (le DNS pointe vers soutade.fr, ça ne plaît pas trop au robot).

Domain: teamazurevasion.fr
Type:   unknownHost
Detail: No valid IP addresses found for teamazurevasion.fr

Il faut dire que ma configuration est un peu particulière puisque j'ai un premier serveur web/proxy (tournant sous nginx) qui s'occupe des sites statiques ainsi que de la liaison sécurisée (TLS). Il communique par socket avec un second serveur (Apache) pour toute la partie dynamique (PHP, Django). La solution consiste donc à stopper le service nginx et utiliser le mode standalone (une fois le port 443 libéré) pour (re-)générer mes certificats :

service nginx stop
certbot certonly --standalone --expand -d soutade.fr -d www.soutade.fr -d blog.soutade.fr
-d demo-gpass.soutade.fr -d denote.soutade.fr -d dynastie.soutade.fr -d gpass.soutade.fr
-d gpass-demo.soutade.fr -d iwla.soutade.fr -d music.soutade.fr
service nginx start

Une petite entrée de plus dans /etc/crontab et voilà, je n'ai plus à me soucier de la gestion de mes certificats ! Bon, j'aurais également pu déployer des scripts dans /etc/letsencrypt/renewal-hooks/.

J'attendais avec impatiente l'arrivée des wildcards (*.nom.de.domaine) qui devaient être intégrés à partir du 4 janvier, mais étant donné que certbot ne génère qu'un seul fichier certificat (embarquant tous les noms de domaines), j'ai finalement sauté le pas. Bien sûr, un wildcard sera plus pratique pour tout ce qui n'est pas configuré explicitement au niveau de mes serveurs webs. Activation prévue fin février, attendons de voir.