J’ai récemment parlé complexité de mot de passe mais en réalité le problème est souvent ailleurs. La taille et la complexité n’ont aucune importance si quelqu’un peut deviner quel mot de passe vous utilisez après juste quelques essais.
Jean réutilise son mot de passe
Je connais l’email de Jean ? Il me suffit de regarder quels mots de passe il a utilisé sur d’autres sites, et de les tester un à un.
La plupart des sites ont un problème de sécurité un jour ou l’autre. Souvent les données extraites se retrouvent publiques d’une façon ou d’une autre. Parfois on y trouve des mots de passe en clair ou mal protégés. Il suffit de piocher dedans.
Testez Have I Been Pwned, vous verrez que des tiers peuvent déjà connaitre plusieurs de vos mots de passe.
Paul n’a aucune imagination
Je ne connais pas l’email de Paul ? Qu’importe. Je peux déjà tester les mots de passe les plus courants, et les variations de ceux-ci.
Ne vous croyez pas original. Même ajouter une date, un chiffre, un symbole, changer une lettre, inverser le mot de passe, quelqu’un l’a déjà fait. En quelques milliers de combinaisons j’ai déjà énormément de mots de passe habituels.
Même les méthodes « choisir x mots du dictionnaire » sont vulnérables si c’est l’utilisateur qui choisit ses mots dans sa tête. Le plus souvent on tombera dans quelques centaines de mots, toujours les mêmes.
Par le passé j’ai utilisé un personnage de littérature, auquel j’ai ajouté un chiffre et un symbole. Croyez-le ou non, on trouve plus d’une dizaine d’occurrences sur Have I Been Pwned.
Have I Been Pwned
J’ai cité Have I Been Pwned. Ils mettent à disposition une base de tous les mots de passe qui ont publiquement fuité.
Si vous laissez des tiers saisir des mots de passe sur votre service, vous devriez télécharger leur base, puis chercher dedans à chaque fois qu’un de vos utilisateur saisit un nouveau mot de passe. Le mot de passe est déjà dedans ?
Alors il y a un risque de sécurité et vous devriez en alerter l’utilisateur.
Si vous voulez aller plus loin, tentez quelques variations simples : Si le mot de passe se termine par un nombre, essayez les deux ou trois nombres précédents. Si le mot de passe à des symboles ou chiffres en début ou fin, retirerez-les et testez le mot de passe résultant.
Tout ça ne vous coûte quasiment rien si ce n’est un peu de stockage et le téléchargement de la nouvelle base Have I Been Pwned de temps en temps, mais ça va éviter bien des risques à vos utilisateurs.
Je continue mes réflexions sur comment nous, informaticiens, participons à la politique par nos actions.
Il ne tient qu’à nous de refuser de participer à des projets et des organisations du mauvais côté de la ligne morale. Contrairement à d’autres professions, nous avons le choix. Utilisons-le.
Plus que le choix, nous avons un pouvoir, énorme. C’est un des apprentissages des logiciels libres. Nous avons quand même réussi que les plus grandes corporations se sentent obligées de contribuer, même de façon mineure, à des logiciels communs profitant à tous. Nous avons réussi à en faire un argument dans les processus de recrutement.
Imaginez, le temple du capitalisme, les méga startup techno qui contrôlent jusque notre vie privée, obligées de fait de se plier à contribuer au domaine commun. Quel pouvoir !
Nous avons utilisé ce pouvoir pour imposer le libre accès au logiciel et au code source, en nous moquant de qui l’utilise et pour faire quoi, comme si cela ne nous concernait pas.
Que nous importe que l’imprimante gère des listes de personnes à abattre tant que nous avons accès au code source du pilote pour en corriger les défauts. Je ne peux m’exonérer des conséquences de ce que je créé et de ce que je diffuse.
Avec tout le respect que j’ai pour l’énorme œuvre du logiciel libre, j’ai l’impression que nous avons partiellement fait fausse route, privilégiant une vision libertaire amorale plutôt qu’assumer les conséquences de ce que nous créons.
Pire, en faisant le logiciel libre comme l’alpha et l’oméga de toute notion politique et éthique dans le logiciel, nous nous sommes retirés toute capacité à intervenir sur d’autre critères.
Je repense à la licence JSON qui avait fait grand bruit par le passé.
Cette notion m’attire, aussi floue et aussi problématique soit-elle.
Oui, cette licence n’est pas libre. La licence GPL serait incompatible avec icelle. Qu’importe : L’accès au logiciel et à son code source ne me semble pas une valeur si absolue qu’il me faille abandonner tout recul sur ce qui est fait avec le logiciel.
Je ne suis pas seul, en parallèle d’autres ont mis à jour la licence Hippocratic, qui va globalement dans le même sens.
The software may not be used by individuals, corporations, governments, or other groups for systems or activities that actively and knowingly endanger, harm, or otherwise threaten the physical, mental, economic, or general well-being of individuals or groups in violation of the United Nations Universal Declaration of Human Rights
J’ajouterais probablement la convention de Genève, celle des droits de l’enfant, peut-être un texte de portée similaire parlant d’écologie (lequel ?), un lié à la vie privée, etc.
Ça reste flou mais ça permet de tout de même donner un cadre, surtout si on ajoute que l’interprétation à donner à ces textes ne doit pas être moins stricte que celle de l’Europe occidentale de notre décennie.
Peu importe en réalité. Il s’agit de donner une intention. Je n’ai pas cette prétention mais si l’armée ou une corporation sans éthique veut réutiliser mon code, ce n’est pas la licence qui les en empêchera, flou ou pas.
Je ne prétends certainement pas aller devant au tribunal. Ma seule arme est l’opprobre publique et le flou n’est ici pas un problème. La précision juridique n’est pas un besoin. Au contraire, rester au niveau de l’intention permet d’éviter les pirouettes en jouant sur les mots ou en trouvant les failles. Quelque part la formulation de la licence JSON a ma préférence, justement pour ça.
Ça vous parait fou, irréaliste, inapplicable, mais combien d’entre nous auraient trouvés la GPL raisonnable, réaliste et applicable à ses débuts ? Les débats n’ont d’ailleurs pas manqué.
Le seul vrai problème, à mon niveau, est bien celui du logiciel libre, et plus particulièrement de la GPL, incompatible avec toute autre licence qui fait des choix différents. Or la GPL est incontournable dans de nombreuses situations, dans de nombreux contextes.
Une solution pourrait être de proposer une double licence : une licence basée sur l’éthique, tout en prévoyant une exception qui permet de passer sur une AGPL au besoin.
Je rage à chaque fois que je saisis un mot de passe fort et que le site m’envoie bouler parce que je n’ai pas de caractère autre qu’alphanumérique.
Essayons quelque chose d’un peu plus smart pour évaluer la robustesse d’un mot de passe
Développeurs, vous savez probablement tout ça, mais continuez à lire parce que la fin vous est adressée
Traduit autrement, voici le nombre de combinaisons qu’on peut tester, et le même chiffre écrit en puissance de deux (arrondi à la décimale inférieure) :
1 €
3,5 × 10^12
2^41,6
10 €
3,5 × 10^13
2^44,9
100 €
3,5 × 10^14
2^48,3
1 000 €
3,5 × 10^15
2^51,6
10 000 €
3,5 × 10^16
2^54,9
100 000 €
3,5 × 10^17
2^58,2
Quand on vous parle ailleurs de bits d’entropie, ça correspond à ces puissances de 2. Avec 1 000 € on peut tester toutes les combinaisons de SHA 256 d’une chaîne aléatoire de 51 bits.
Ok, mais ça me dit quoi ? Une lettre c’est 26 combinaisons, environ 4,7 bits. Si vous ajoutez les majuscules vous doublez le nombre de combinaisons et vous ajoutez 1 bit. Si vous ajoutez les chiffres et quelques caractères spéciaux on arrive à à peine plus de 6 bits.
Petit calcul, en utilisant juste les 26 lettres de l’alphabet, on peut tester toutes les combinaisons de 8 caractères pour moins de 1 €. Vu qu’on aura de bonnes chances de tomber dessus avant d’avoir testé toutes les combinaisons, autant dire que même avec 9 caractères, votre mot de passe ne vaut pas plus de 1 €.
Combien faut-il de caractères pour se trouver relativement à l’abri (c’est à dire que la somme investie ne peut pas tester plus de 1% des combinaisons) ? Ça va dépendre de ce que vous y mettez comme types de caractères. J’ai fait les calculs pour vous :
a-z
a-z A-Z
a-z A-Z 0–9
a-z A-Z 0–9 +-%
1 €
11
9
9
8
10 €
11
10
9
9
100 €
12
10
10
10
1 000 €
13
11
10
10
10 000 €
14
11
11
11
100 000 €
14
12
11
11
Et là magie : 8 caractères, même avec des chiffres, des majuscules et des symboles, ça résiste tout juste à 1 €. Et encore, là c’est en partant du principe que vous choisissez réellement les caractères de façon aléatoire, pas que vous ajoutez juste un symbole à la fin ou que vous transformez un E en 3.
Vous voulez que votre mot de passe résiste à un voisin malveillant prêt à mettre plus de 10 € sur la table ? Prévoyez au moins 10 caractères.
Et là, seconde magie : Si vous mettez 10 caractères on se moque de savoir si vous y avez mis des chiffres ou symboles. La longueur a bien plus d’importance que l’éventail de caractères utilisé.
Maintenant que vous savez ça, tous les sites qui vous imposent au moins une majuscule et un symbole mais qui vous laissent ne mettre que 8 caractères : Poubelle.
Je ne suis pas en train de vous apprendre à faire un mot de passe fort. Vous devriez utiliser un gestionnaire de mots de passe et le générateur automatique qui y est inclus.
Je suis en train d’essayer de rendre honteux tous les développeurs qui acceptent de mettre ces règles à la con sur les sites web dont ils ont la charge : Vous imposez des mots de passe qui sont à la fois imbitables et peu robustes.
Vous voulez faire mieux ?
Regardez dans quelle colonne est l’utilisateur en fonction des caractères qu’il a déjà tapé et donnez-lui un indicateur en fonction de la longueur de son mot de passe.
Moins de 10 € ? mot de passe insuffisant, refusé
Moins de 100 € ? mot de passe faible, couleur rouge
Moins de 1 000 € ? mot de passe moyen, couleur orange
Mot de passe sûr, couleur verte, à partir de 10 000 €
Si vous gérez un site central, par exemple un réseau social public, vous pouvez probablement relever tout ça d’un cran.
Si ça donne accès à des données sensibles, à des possibilités d’achat, à la boite e-mail ou à l’opérateur téléphonique, mieux vaux relever tout ça de deux crans.
Le tout prend probablement moins de 10 lignes en javascript. C’est une honte que vous acceptiez encore d’implémenter des règles à la con « au moins une majuscule, un chiffre et un symbole, voici les symboles autorisés […] ».
Il y a peut-être des erreurs, probablement des mauvais termes, certainement des fautes ou mauvaises formulations. Vous êtes bienvenus à participer en proposant des corrections.
L’idée de base : Tous les mots de passe sont chiffrés. Personne d’autre que vous ne peut les relire sans votre accord. Ni le serveur sur lequel vous les envoyez, ni quelqu’un qui a accès au disque où vous les stockez, ni quelqu’un qui a ponctuellement accès à votre poste de travail.
Chiffrer c’est simple.
Pour chiffrer on a le choix. On va séparer deux catégories principales de chiffrement : les chiffrements symétriques et les asymétriques.
La plupart des gestionnaires de mots de passe ont choisi un chiffrement symétrique (une seule clef secrète qui sert à la fois à chiffrer et à déchiffrer). C’est simple à gérer, rapide à l’exécution, et il n’y a pas besoin de clef de grande taille. Tous ceux que j’ai vu utilisent de l’AES avec une clef de 256 bits. Au moins pour Bitwarden et Keepass, c’est le mode CBC, et un contrôle HMAC avec SHA256 comme fonction de hachage (mais vous pouvez ignorer tous ces détails s’ils ne vous disent rien).
J’ai dit « la plupart des gestionnaires de mots de passe ». Un projet au moins a fait un choix différent. L’outil pass utilise un chiffrement asymétrique (une clef publique et une clef privée, l’une sert à chiffrer et l’autre à déchiffrer). Plus exactement, ils utilisent l’outil GnuPG. Même si le choix de la clef est libre, par défaut on y utilise généralement une clef RSA de 2048 bits. Pass a fait ce choix en considérant le partage de mots de passes comme la fonctionnalité principale. On verra pourquoi quand on parlera partage. Entre temps on va se concentrer sur ceux qui font du chiffrement symétrique.
Dans les deux cas, on est là dans de l’ultra-standard au niveau cryptographie. Je serais étonné de voir autre chose ailleurs (et c’est une bonne chose).
Une clef ? quelle clef ?
Ok, nos mots de passe sont chiffrés mais où est la clef ?
Impossible de demander à l’utilisateur de se rappeler une clef de 256 bits. Ce serait plus de 40 signes entre minuscules, majuscules, chiffres et caractères spéciaux. Même avec une très bonne mémoire, ce serait ingérable à l’usage.
Stocker la clef de chiffrement en clair sur le disque n’est pas beaucoup mieux. Ce serait comme avoir coffre-fort haute sécurité dont on cache la clef sous le paillasson.
Ce qu’on demande à l’utilisateur c’est un mot de passe principal. Vu qu’il va permettre de déchiffrer tous les autres, on va l’appeler « mot de passe maître ». Il faut qu’il soit assez long et complexe pour éviter qu’un tiers ne puisse le deviner ou le trouver en essayant toutes les combinaisons une à une, mais assez court pour pouvoir s’en rappeler et le taper sans erreur.
Le mot de passe maître ne chiffre rien lui-même. Accompagné d’autres paramètres, il sert à calculer une clef de taille suffisante qui, elle, servira au chiffrement décrit plus haut et qu’on va appeler « clef maîtresse ». La fonction qui fait cette opération est dite fonction de dérivation de clef.
Bitwarden utilise le très classique PBKDF2 avec un hachage SHA256. Pour faire simple on prend le mot de passe, on le mélange à une chaîne aléatoire (stockée quelque part pour réutiliser la même à chaque fois), et on opère la fonction de hachage prévue. Normalement ça suffit pour avoir un résultat considéré comme relativement aléatoire et impossible à remonter en sens inverse.
En pratique on cherche aussi à ralentir quelqu’un qui chercherait à tester tous les mots de passe possibles un à un. Pour ça on va simplement répéter l’opération précédente un certain nombre de fois. Chaque itération prend en entrée le résultat de l’étape précédente. Si je fais 10 itérations, il faudra 10 fois plus de temps à un attaquant pour tester toutes les combinaisons. Ici on considère le résultat comme assez confortable à partir de 100.000 itérations.
Keepass utilise une fonction plus récente et considérée comme plus robuste aux possibilités des matériels actuels : Argon2.
Là aussi tout est très classique. Je n’ai pas regardé tous les gestionnaires de mots de passe mais je serais étonné de trouver autre chose que ces deux solutions standards.
On résume
À l’ouverture le gestionnaire de mots de passe vous demande votre mot de passe maître. À partir de ce mot de passe et de paramètres prédéterminés, il utilise une fonction de dérivation de clef et en sort une clef maitresse.
C’est cette clef maitresse qui permet de chiffrer ou déchiffrer vos mots de passe. Celui qui n’a pas accès à votre clef ne pourra rien faire des mots de passe chiffrés sur le disque.
Sécurité
À l’ouverture, le gestionnaire de mot de passe vous demandera votre mot de passe maître que pour calculer la clef maîtresse à l’aide d’une fonction de dérivation de clef. Une fois ceci fait, il garde la clef maîtresse en mémoire et oublie le reste. Quoi qu’il se passe, personne ne connaîtra votre mot de passe maître.
Le logiciel utilise cette clef maîtresse pour chiffrer et déchiffrer vos mots de passe. Cette clef maîtresse n’est jamais écrite nulle part. La plupart des gestionnaires de mots de passe oublieront volontairement cette clef en mémoire après un certain temps d’inactivité, ou à la mise en veille de votre poste de travail. L’idée c’est de limiter le risque de laisser qui que ce soit d’autre que vous y avoir accès. Dans ces cas là, on vous invitera à saisir de nouveau votre mot de passe maître pour retrouver la clef oubliée.
Une fois la clef maîtresse hors de la mémoire, vous n’avez que des blocs chiffrés que personne ne pourra déchiffrer sans le mot de passe maître. Pas même vous. Si vous oubliez votre mot de passe maître, vous ne pourrez plus jamais relire ce que vous avez stocké. Même votre ami qui s’y connait ne pourra rien pour vous.
Ne vous laissez toutefois par leurrer. On parle sécurité, chiffrement, complexité des fonctions de dérivation de clef, mais en réalité tout ça a peu d’importance comparé à votre mot de passe maître. C’est un peu comme un coffre-fort : Discuter du diamètre des barres de renfort n’a aucun intérêt s’il s’ouvre avec une combinaison de trois chiffres seulement.
S’il est possible de trouver votre mot de passe avec un nombre de tentatives limité, tout le reste ne servira à rien. « Limité » dans ce cas, ça dépasse la centaine de milliards de combinaisons. Il vaut mieux un mot de passe maître complexe avec une fonction de dérivation simple qu’un mot de passe maître simple avec une fonction de dérivation complexe.
Changer le mot de passe
Les plus alertes d’entre vous auront remarqué que si tout est déchiffré indirectement à partir du mot de passe, changer le mot de passe fait perdre l’accès à tout ce qui est déjà chiffré.
Quand vous changez votre mot de passe maître, Keepass déchiffre toutes les données en mémoire, calcule la nouvelle clef et rechiffre l’intégralité des données. Même si vous gérez une centaine de mots de passe, c’est quelque chose qui se fait rapidement sans avoir besoin de vous faire patienter longtemps.
Bitwarden utilise lui une clef intermédiaire totalement aléatoire appelée clef de chiffrement. C’est cette clef qui sert en réalité à chiffrer et déchiffrer les données stockées. Elle est elle-même chiffrée, à partir de la clef maîtresse, et stockée à côté des données.
On a donc un mot de passe maître qui sert à calculer une clef maîtresse. La clef maîtresse sert à déchiffrer la clef de chiffrement. La clef de chiffrement sert à chiffrer et déchiffrer les données sur le disque.
Lorsqu’on veut changer de mot de passe il suffit de chiffrer la clef de chiffrement avec la nouvelle clef maitresse. Il n’y a pas besoin de rechiffrer chaque donnée (vu que la clef de chiffrement ne change pas, elle).
L’avantage n’est pas tant dans le temps gagné (peu significatif) mais dans la résistance aux accès concurrents : On peut avoir plusieurs clients qui lisent et écrivent en parallèle des données différentes dans le même trousseau sans crainte que l’un d’eux n’utilise encore une ancienne clef de chiffrement et envoie des données illisibles par les autres.
Et justement, et si je partage ?
Avec ce qu’on a vu jusqu’à présent, si je partage des mots de passe je dois aussi partager la clef de chiffrement utilisée.
Bitwarden permet de partager des mots de passe à un groupe de plusieurs personnes (appelé « organisation »). Au lieu d’être chiffrés avec ma clef de chiffrement personnelle, ces mots de passe sont chiffrés avec une clef de chiffrement dédiée à l’organisation.
Le gros enjeu n’est pas dans le chiffrement mais dans comment transmettre cette clef d’organisation à chaque utilisateur de l’organisation.
Il faut un moyen pour que l’administrateur de l’organisation chiffre la clef d’organisation, me l’envoie sur le serveur d’une façon que seul moi puisse la relire.
Jusqu’à maintenant c’est impossible parce que nous utilisons des clefs symétriques. C’est la même clef qui sert au chiffrement et au déchiffrement. Si l’administrateur pouvait chiffrer avec ma clef, il pourrait aussi déchiffrer tous mes mots de passes personnels et ça c’est inacceptable.
C’est donc ici qu’on reparle des clefs asymétriques RSA. Chacun a une clef publique (diffusée à tout le monde) et une clef privée (garder secrète par chaque utilisateur). La clef publique sert à chiffrer. La clef privée sert à déchiffrer. Tout le monde est donc capable de chiffrer quelque chose avec ma clef publique, mais seul moi pourrait le déchiffrer.
La clef RSA fait 2048 bits mais ne vous laissez pas impressionner, ces 2048 bits sont en fait moins robustes que les 256 bits d’AES.
L’administrateur de l’organisation récupère ma clef publique, chiffre la clef d’organisation à l’aide de ma clef publique, et envoie ça sur le serveur. Quand je voudrais chiffrer ou déchiffrer quelque chose dans l’organisation, je récupère la clef d’organisation chiffrée avec ma clef publique, je la déchiffre avec ma clef privée, et je m’en sers dans mes opérations de chiffrement.
Ok, mais il va me falloir sécuriser ma clef privée. On a déjà les outils pour ça, il suffit de la chiffrer ! Bitwarden la chiffre donc avec la clef de chiffrement, celle dont on a déjà parlé plus haut.
On a donc un mot de passe maître qui sert à calculer une clef maîtresse. La clef maîtresse sert à déchiffrer la clef de chiffrement. La clef de chiffrement sert à déchiffrer ma clef RSA privée. La clef RSA privée sert à déchiffrer la clef d’organisation. La clef d’organisation sert à chiffrer et déchiffrer les données.
Pfiou! Ça semble long et complexe mais tout utilise toujours le même principe et la plupart de ces opérations ne servent qu’à l’initialisation logiciel quand vous le déverrouillez.
Rappelez-vous, votre clef de chiffrement ne change pas quand vous changez votre mot de passe. Pas besoin donc de changer ou rechiffrer vos clefs RSA non plus.
Et Pass alors ?
Pass fait le choix de sauter tout le chiffrement symétrique et de n’utiliser que l’asymétrique. Un dépôt contient les clefs GPG de tous les membres (clefs publiques). Chaque fois qu’un mot de passe est chiffré, il l’est avec toutes ces clefs. Quand un membre veut lire un des mots de passe, il le déchiffre avec sa propre clef privée.
Quand on ajoute un membre, quand on change une clef, il faut tout rechiffrer.
J’aurais évité autant que possible il y a 15 ans, aujourd’hui je suis amoureux des import explicites en début de fichier, sans aucun symbole externe qui ne soit importé explicitement. Pas de symbole chargé ou défini dans un autre fichier magiquement accessible ailleurs, pas même d’import *. Si je m’écoutais en ce moment je voudrais même importer les types de base du langage.
Mon historique PHP et Ruby m’ont longtemps fait voir l’absence de tout ça comme un avantage. Ça n’est vrai qu’avec de très bon IDE. En pratique ça ne permet pas de savoir où est défini le symbole, s’il existe vraiment, ni de gérer correctement les conflits de noms et surcharges locales.
Il y a souvent tellement peu de modules, classes et fonctions externes différentes dans un fichier bien structuré que l’explicite apporte bien plus de bénéfices que de pénibilité. Si on dépasse la dizaine c’est le symptôme que quelque chose ne va pas par ailleurs
Côté syntaxe j’apprécie celle de Python qui montre ce qui est important systématiquement en fin de ligne.
from xxx import A, B, C as D
Les imports Javascript sont pratiques mais la partie la plus significative se retrouve en milieu de ligne, pas toujours là où c’est visuellement le plus identifiable (sans compter la dualité entre import A et import { A })
Soyons fous, on pourrait même importer les objets de base du langage avec un import { String, Integer, Array } from StdLib. On n’en utilise pas plus d’une poignée dans un même fichier. Point bonus si ça permet que "hello", 42, ou [1, 2, 3] soient des raccourcis de syntaxe vers les classes ainsi déclarées en haut de fichier et n’utilisent pas forcément les classes natives du langage.
import { String, Integer } from Stdlib
import { MyArray as Array } from MaLibPerso
import { MACONSTANTE, MaClasse } from MonAutreLibPerso
Quitte à faire une liste de course, pourrait-on faire que les imports avec un chemin absolu « /dir/sub/fichier » référencent la racine du projet et pas la racine du système de fichier ?
Il n’y a que les imbéciles qui ne changent pas d’avis et c’est mon avis depuis toujours
Coluche
J’ai toujours regardé avec dédain les tentatives des dev JS pour contourner l’écriture de CSS mais je commence à considérer que les outils de CSS-in-JS type Emotion sont la bonne solution pour les webapp React.
J’ai été intégrateur, à faire de la belle CSS séparée du code HTML. On finit quand même vite par construire des monstres ou se prendre les pieds dans le tapis dès qu’on fait plus de quelques pages types.
Pour résoudre le problème, éliminons le. C’est ce que proposent les conventions comme BEM. Si je caricature, il s’agit principalement de retirer les sélecteurs CSS un attribuant une ou plusieurs classes spécifiques à chaque contexte. C’est franchement moche mais ça fonctionne.
CSS-Modules va un peu plus loin. Le principe est le même mais on permet au développeur d’utiliser un nommage plus agréable. C’est l’outil de génération qui gère la complexité au lieu du développeur.
J’avoue que j’aime bien CSS-modules. C’était mon favori jusqu’à présent.
Ça revient à juste gérer un fichier par composant en se limitant à des sélecteurs très simples pour ne pas créer de conflits de spécificité. On reste sur du CSS standard et sur une approche proche de mes habitudes historiques. Mieux : L’intégration peut se faire indépendamment du langage de développement de l’applicatif.
C’est top mais ça se base sur des composants qui ne bougent pas beaucoup, dont on connait à l’avance tous les états.
Dès qu’il s’agit de cumuler plusieurs états, le résultat dépend de l’ordre d’écriture dans la CSS. Parfois c’est bien prévu, parfois non.
Dès qu’il s’agit de rendre des choses très dynamiques, il faut de toutes façons sortir des CSS modules. Vous voulez que dans la vue large les items de navigation se colorent au survol en fonction de la catégorie destination déterminée dynamiquement mais qu’ils utilisent la couleur neutre dans la vue réduite destinée aux mobiles ? Vous êtes à poil et il va falloir composer avec d’autres façons d’injecter des CSS, peut-être même tâtonner sur les priorités entre classes.
Les classes utilitaires et CSS atomiques à la Tachyon sont là pour industrialiser en poussant encore plus loin.
J’ai une classe par valeur à appliquer : .ms7-ns applique la septième valeur du catalogue (7) comme taille horizontale maximum (ms pour max-width) si la fenêtre a une taille supérieure au point de rupture « small » (ns pour non-small).
Ça n’offre quasiment aucune abstraction utile (uniformiser les valeurs on a déjà plein d’outils plus efficaces). C’est vite cryptique, lourd, et monstrueux dès qu’on multiplie les valeurs et les points de rupture possibles.
Le seul intérêt par rapport à écrire directement les attributs style c’est que ça permet d’accéder aux media query et aux pseudo-sélecteurs.
Malheureusement non seulement ça ne résout pas les conflits de priorités mais ça les empire. Si je spécialise un composant existant en y ajoutant une classe liée à une directive déjà présente, je joue à la roulette russe. Il faut absolument que mon composant initial prévoit lui-même tous les cas possibles pour savoir quelle classe injecter et ou ne pas injecter. Pas d’alternative.
J’ai vraiment l’impression d’un retour en arrière monstrueux avec ces CSS atomiques, cumuler les défauts sans aucun avantage, et c’est probablement ce qui m’a fait rejeter par principe les CSS-in-JS jusqu’alors.
Les CSS-in-JS c’est finalement pousser la logique de Tachyons un cran plus loin. Quitte à décider de tout dans le code HTML, autant écrire directement les styles à cet endroit là en utilisant la vraie syntaxe CSS et en y ajoutant la possibilité d’accéder aux media query et aux pseudo-sélecteurs.
Emotion c’est ça. On est à la croisée entre le « j’écris tout dans un attribut style » et le « j’attache un module CSS ».
En fonctionnement basique c’est comme un CSS module sans le sélecteur. Je donne les directives en CSS on ne peut plus classiques et j’ai accès aux media query, aux pseudo-sélecteurs et aux animations avec une syntaxe proche de ce que font les préprocesseurs habituels (et en phase avec la direction que prend la syntaxe CSS elle-même).
Je peux directement ajouter le résultat aux classes CSS de mon composant. Il se chargera de générer un nom de classe, de créer la CSS correspondante dans le document, et de lier les deux, comme avec CSS-Modules.
L’exemple est peu parlant. On a juste l’impression d’un CSS-Modules écrit dans le fichier JS.
L’avantage c’est que je ne suis pas limité aux valeurs en dur. Je peux avoir des valeurs dynamiques venant de mon Javascript ou de mon thème, et je n’en limite pas les effets à ce que me permettent les variables CSS.
Je peux aussi réutiliser, composer ou surcharger un élément ou un bloc de styles avec un autre sans risque de conflit de priorité.
Tachyons me donnait l’impression de cumuler les inconvénients, ici j’ai vraiment l’impression de cumuler les avantages.
La seule contrainte c’est que mon code CSS se retrouve dans mes fichiers JS. C’est moche quand c’est dit ainsi mais pour une app en React, on a de toutes façons un fichier par composant HTML et ça a du sens de grouper HTML, JS et CSS lié au composant ensemble quand ils sont fortement liés. C’est d’ailleurs le choix de VueJS.
Ce n’est forcément pas adapté à tout, et si vous voulez rester génériques les CSS-Modules sont à mon avis l’option la plus saine, mais pour un code React je crois que c’est là que je commencerai par défaut désormais.
J’ai toujours été gêné par l’intégration de grosses modifications dans git.
Dans l’idéal on fait une série de modifications autonomes, on les soumet à la revue des pairs puis on les intègre dans les branche principale qui peut partir en production à tout moment.
Ça c’est la théorie. En pratique je fais des erreurs que je ne vois qu’à la fin des modifications. Mes collègues auront de toutes façons des retours sur ce que j’ai poussé en ligne et me demanderont des modifications avant l’intégration finale. Si ce n’est pas le cas au moins une fois sur deux, c’est que nous travaillons mal.
Et là… les ennuis commencent.
Mes modifications ne sont plus autonomes. J’ai des correctifs à la fin. Potentiellement mes modifications précédentes sont donc incomplètes, de mauvaise qualité ou même défaillantes. Si j’intègre mon code à la fin de la revue, je casse toute la belle théorie.
La première pratique c’est d’intégrer le code tel quel sur la branche master. C’est ce qui m’apparait le plus cohérent. Le code de la branche est potentiellement instable mais tous les points d’étape de master sont de qualité. Pour parcourir les modifications de la branche master on ajoute --merges --first-parent histoire de ne pas voir les modifications internes des sous-branches. Ni vu, ni connu mais le débogage de la branche après coup en cas de besoin ne sera pas idéal.
L’alternative est de fusionner en une seule toutes les modifications de la branche lors de son intégration. On perd toute la granularité et ça peut rendre bien plus difficile de tracer l’origine d’une anomalie par la suite, ou de comprendre le pourquoi et le comment d’un changement. C’est encore viable sur 100 voire 200 lignes bien groupées mais ça devient franchement litigieux au delà.
La seule pratique que je réprouve totalement est celle du rebase sans squash. On importe tous les changements directement sur master et on perd totalement la capacité d’avoir un master stable. Ne faites pas ça.
La troisième voie c’est la réécriture de l’historique.
En théorie c’est mal, au moins pour les branches déjà publiées. En pratique tant qu’aucun autre code ne se base dessus, ça ne pose pas vraiment de problèmes. Sur des équipes en entreprise ça se maitrise assez bien. Sur du code open source ça me semble plus litigieux. Github le gère parfaitement dans les pull-request en cours de revue.
Les vrais, les purs, le font en ligne de commande. Je suis admiratif devant ceux qui savent découper une modification ou ajouter un correctif dix changements en arrière dans l’historique sans réfléchir ni tout casser. Techniquement ça ne pose pas vraiment de difficultés mais c’est long, propice aux erreurs, et le moindre faux pas peut faire de gros dégâts irrémédiables. Je ne trouve pas les interfaces graphiques inutiles pour tout ça.
Et là, merci Patrick, gitup vient désormais à ma rescousse. L’interface est simpliste, pas toujours pratique, mais elle fait ce que je n’ai pas vu ailleurs.
Je suis capable de séparer un changement en deux quelle que soit sa position dans l’historique ;
Je suis capable de déplacer un changement en haut ou en bas dans l’historique d’un simple raccourci clavier ;
Je suis capable de faire un correctif, le descendre dans l’historique, puis le fusionner avec le changement initial qu’il faut corriger.
Tout ça graphiquement, avec la possibilité de revenir en arrière quand je veux si jamais je fais des bêtises.
Le projet Lima s’éteint. C’est dommage. Je suis convaincu que les équipes de Lima ont fait tout ce qu’elles pouvaient pour que ça n’arrive pas. Des fois « on n’y arrive pas ». C’est dommage mais c’est ainsi et on doit plutôt remercier les gens d’avoir essayé.
Les appareils concernés vont à terme devenir inutilisables. C’est un bon exemple de « n’utilisez pas d’appareils connectés qui dépendent d’un service centralisé » mais à mon sens la leçon n’est pas celle là.
Je n’aime pas tirer sur l’ambulance mais mon problème est un problème éthique.
What happens if CGC dies ?
What’s good with Lima is that it’s entirely private and decentralized. So Lima can work independently from any servers, and continue managing your data even if our startup dies (disclosure: we don’t plan anything like that)
The only thing we manage on our side of the equations are updates of our app and the web interface of Lima. In case of company crash, we’ll do our best to open source at least the most critical parts of our code, so the community continues improving the solution every night.
La disparition de l’entreprise a été envisagée dès le début de l’aventure (c’est bien) et des éléments de réassurance ont été posés (c’est bien aussi, même si ce n’est que du best effort).
J’ai un problème éthique parce que toutes les équipes de Lima, des fondateurs jusqu’aux développeurs ont accepté de poser ces éléments de réassurance alors qu’ils semblent faux.
En pratique le serveur de l’infrastructure Lima est un composant essentiel et les boitiers vont progressivement arrêter de fonctionner. Ce n’est pas moi qui le dit, c’est Lima eux-mêmes. Là on est dans la tromperie pure et simple par rapport à la promesse affichée.
While your Lima product synchronises with your devices without servers, our servers are still needed to make your devices find each other and establish a connection.
Unfortunately, as our services shut down, your Lima will progressively stop to work.
La promesse de l’open source est similaire. En pratique il est impossible de passer le code open source une fois la société en liquidation. C’est confirmé par les réponses sur Twitter.
C’est simplement légal. Les actionnaires perdent le contrôle de la société et le liquidateur a l’obligation légale de tirer le maximum des possessions de la société. Ça inclut le code source et la propriété intellectuelle. Libérer le code source gratuitement n’est légalement plus possible.
If there’s any way, we will. But unfortunately the complexity of IP law makes it difficult: it is no longer up to us.
Il aurait fallu s’y prendre avant le début des difficultés. Il aurait fallu déposer le code source régulièrement chez un tiers de confiance et s’engager contractuellement avec lui sur une cession de droits qui ne deviendra effective qu’à certaines conditions pré-établies.
Même si la FAQ parle de « do our best », on est dans la tromperie. Il n’est pas imaginable que la question ait été abordée dans la FAQ et que les collaborateurs de l’entreprise aient pu ignorer les enjeux ci-dessus. Ils semblent pourtant ne rien avoir prévu, consciemment, et avoir participé là aussi à un décalage significatif entre le discours et les actions.
J’en veux aux développeurs qui ont participé à ça, et qui vont mettre le doute sur tous les autres.
Développeurs, vous ne devriez pas mettre l’éthique de côté. Vous ne devriez pas apporter votre concours à des sociétés qui trichent, qui trompent, peu importe le degré de coolitude du produit ou du service.
Un des premiers mensonges qu’on vous livre trop souvent avec SCRUM c’est qu’on peut estimer des petites tâches avec bien plus de précision que des grandes, et qu’en conséquence on peut être assez fiable dans l’estimation des une à trois semaines de chaque itération.
Foutaises !
Combien de temps faut-il pour mettre les blousons avant d’aller à l’école ? Mettons 30 secondes si on ne se presse pas. La réalité c’est que ça mettra plus souvent 5 minutes que 30 secondes, et ça c’est si on n’a pas besoin de se battre.
400% de marge d’erreur ? Comment voulez-vous faire un planning avec de telles estimations. Pourtant on est sur une tâche connue, répétée chaque jour. Seule solution, on triche et on compte 2 minutes 30. Même ainsi on a une marge d’erreur de 100%. Hallucinant !
Ce n’est pas un exemple choisi. J’ai le même problème pour terminer la tartine, pour boire le verre d’eau ou pour passer aux toilettes avant de partir, pour descendre dans la rue, pour faire le trajet, pour trouver le badge et passer le portail de l’école, pour montrer ma carte au vigile, pour les 10 mètres dans l’école au milieu des copains et autres parents d’élèves, pour le bisou de bonne journée avant de pouvoir repartir…
Ce n’est pas non plus la faute d’une mauvaise analogie. Estimer une petite tâche est juste impossible parce que le moindre aléa fait tout exploser.
Ajouter un lien sur une page ça prend 30 secondes… sauf si on vous dit de changer l’URL au dernier moment et qu’il faut faire deux fois le travail, sauf si c’est le seul lien à cet endroit et qu’il faut retoucher les règles de style, sauf si le lien passe à la ligne en plein milieu et que visuellement ça ne le fait pas du tout sur ce composant, sauf si l’espace pris fait glisser le bouton qui suit sous le clavier sur un smartphone une fois le clavier déplié, sauf s’il faut partir à la chasse de la bonne URL parce que c’était « ça n’a pas d’impact, on donnera le lien au dernier moment », sauf si on se rend compte qu’il faut mutualiser ce lien avec autre chose ailleurs dans l’application, sauf si ajouter un lien casse le test end-to-end et qu’il faut le réécrire pour faire passer le serveur d’intégration continue au vert, sauf si… pour un simple foutu lien !
Et pourtant, on n’est jamais en retard à l’école. Malgré les aléas infinis à chaque tâche, le projet « aller à l’école » prend 45 minutes à ±15 minutes. Pas plus.
Ce n’est même pas qu’estimer le projet dans son ensemble permet de lisser les risques de dérapages, c’est que le temps que prend chaque tâche dépend de toutes les tâches précédentes et des options qu’il nous reste pour les suivantes.
S’il faut lutter pour terminer le croissant alors on active sérieusement la suite. Si les toilettes s’éternisent je prépare le blouson et le bonnet pendant ce temps. S’il le faut on presse un peu le pas. À l’école, si on arrive dans les derniers, aucun parent d’élève ou camarade ne nous retient dans les dix derniers mètres et le bisou sera vite fait. Si vraiment on est super en retard on peut toujours sortir le vélo ou prendre le tram.
En réalité si SCRUM estime les fonctionnalités unitaires ce n’est pas pour s’engager sur un résultat donné à l’avance, ni même pour mesurer si l’itération a été une réussite ou un succès lors de la rétrospective. C’est uniquement pour savoir où on va dans la boîte de temps qu’on s’est donnée. Rien de plus.
Quand on vous dit que ça permet d’être plus fiable, derrière se cache l’hydre du « on va transformer vos estimations en engagement » voire du « on va ajouter vos estimations une à une et ça donnera la deadline de fin de projet si rien ne change ».
Ami, tu viens d’être éligible à la fibre ou de déménager là où la fibre est présente. Tu cherches un opérateur.
Ne fais pas attention au débit. Si tu viens de l’ADSL ça va être le jour et la nuit quoi que tu choisisses comme offre fibre. Tu auras des offres allant de 200 Mb/s à 10 Gb/s, à comparer à ton ADSL qui se situe quelque part entre 8 et 20 Mb/s en descendant et au mieux 1 Mb/s en montant.
En réalité tu ne verras pas de différence significative au jour le jour entre les offres à 300 Mb/s et les offres à 1 Gb/s. Tu n’atteindras de toutes façons que rarement de tels débits de toutes façons. Ne parlons même pas du 10 Gb/s, là on est dans du marketing.
Regarde tout le reste : la qualité de la box, regarde le prix initial mais aussi si ce n’est pas une offre promotionnelle pour les 12 premiers mois qui va doubler au bout d’un an, regarde les frais d’installation ou de résiliation, regarde s’il y a une offre TV qui te correspond, regarde les délais habituel de l’opérateur pour les installations, regarde la qualité de leur support client, etc. Tout ça a bien plus d’importance que le débit des offres fibre, et te touchera de façon bien plus forte.
La réalité est plus complexe que le dépliant du fournisseur d’accès
On a tous envie de se dire qu’entre 10 Gb/s (10 000 Mb/s) et 300 Mb/s, ça se voit un peu quand même. La réalité est plus complexe. Ce chiffre ne reflète que le débit théorique entre la box et le fournisseur d’accès.
Déjà chez toi : Si tu es sur WIFI, tu peux oublier l’idée d’aller à plus de 500 Mb/s en pratique même en t’asseyant juste à côté de ta box. Pour aller plus loin il faudrait un câble ethernet. Ils sont déjà loin les 10 Gb/s. En réalité sur un appartement un peu bruité, avec un peu de distance, c’est déjà très bien si on arrive à faire du 300 Mb/s en pratique. Ne parlons même pas d’avoir un mur entre le poste informatique et la box. Si c’est pour travailler à partir d’une carte SD tu n’approcheras de toutes façons même pas les 100 Mb/s.
Ensuite en face : Non le serveur d’en face ne te permettra généralement pas d’échanger en Gb/s de toutes façons. Même 300 Mb/s tu ne le trouveras pas si souvent. On en est au point où régulièrement il y a des bisbilles avec Youtube, Netflix et les autres parce que les échanges entre eux et les fournisseurs d’accès ne dépassent pas la dizaine de Mb/s aux heures de pointe.
Et de toutes façons sur l’usage : Les hauts débits se trouvent quand tu télécharges un gros contenu de façon soutenu. Tu envoies des fichiers de quelques Mo ou moins ? le temps sera plus dépendant du nombre de fichiers que de la bande passante disponible. Tu fais de la navigation web ? à ces vitesses le temps d’affichage dépend bien plus du développeur du site que de la capacité de ta ligne.
Et fais attention à SFR : Si tu déménages dans un appartement existant et que ni Orange ni Free ne proposent pas d’offre fibre pour ton appartement, il est probable que ton immeuble soit câblé et non fibré (oui, même si SFR continuera à te dire que c’est de la fibre). Tu peux le vérifier facilement : Si ça ressemble à une prise d’antenne TV, que ça a un diamètre plus proche d’un câble d’antenne TV que d’un petit cable USB, c’est du câble coaxial et pas de la fibre.
Là (coaxial SFR) toutes les installations ne sont pas équivalentes. Certaines montent effectivement jusqu’à 1 Gb/s, d’autres non. Tu auras souvent toutes les peines du monde à obtenir le vrai chiffre de la part de leur service commercial qui te servira du « jusqu’à 1 Gb/s » ad libitum . Bref, acheter une offre plus chère afin d’avoir un plus haut débit théorique et remarquer que c’est finalement bridé par l’installation en place, ça serait dommage.
Je ne dis pas que tu ne dépasseras jamais les 300 Mb/s mais ça ne représentera pas ton quotidien. Même s’il t’arrive de télécharger des contenus vidéos ou des grosses archives à partir d’un ordinateur branché par câble, la différence entre 300 Mb/s et 1 Gb/s, c’est télécharger un DVD complet en environ 100 secondes au lieu de 30. Je doute que l’attente supplémentaire soit de nature à influencer sur le choix de l’offre Internet.
Si vraiment tu veux regarder le débit, regarde le débit montant
Le débit descendant c’est celui que tu utilises pour télécharger quelque chose en provenance d’Internet. C’est celui qui est généralement mis en avant parce que le plus gros des deux.
Celui qui peut t’intéresser c’est le second, qui sert à envoyer des contenus vers Internet. Il doit t’intéresser parce qu’il est généralement bien plus petit.
Ce n’était pas important sur ADSL parce que le débit ne te permettait pas grand chose d’autre que du descendant. Avec la fibre tu vas probablement brancher un Google Drive, un Dropbox, peut-être un logiciel de sauvegarde. Tu vas vouloir envoyer d’énormes photos voire des vidéos ou de monstrueux documents bureautiques pas optimisés. Bref, l’usage va changer et ce serait dommage d’avoir un débit trop ridicule en montant.
Entre le 200 (descendant) / 50 (montant) de SFR et le 300 (descendant) / 300 (montant) de Sosh, tu as beaucoup plus de chances de ressentir la différence de débit montant que la différence de débit descendant (même si 50 Mb/s en montant ça reste 50 fois mieux que ce que tu avais en ADSL, et pas ridicule du tout, donc pas forcément le critère).