URL: https://linuxfr.org/users/gouttegd/journaux/pebble-un-client-en-ligne-de-commande-pour-passman Title: Pebble, un client en ligne de commande pour Passman Authors: gouttegd Date: 2021年08月26日T23:45:31+02:00 License: CC By-SA Tags: gestionnaire_de_mots_de_passe et framasoft Score: 21 ’Jour ’Nal, Aujourd’hui je te présente un petit outil de mon cru, un client en ligne de commande pour le gestionnaire de mots de passe [Passman](https://github.com/nextcloud/passman). # Introduction Passman est un gestionnaire de mots de passe qui se présente sous la forme d’une application [Nextcloud](https://nextcloud.com/). Il fournit naturellement un client web (intégré à l’interface de Nextcloud), ainsi qu’un [client pour Android](https://github.com/nextcloud/passman-android) et une [extension pour navigateurs](https://github.com/nextcloud/passman-webextension). En revanche, il n’existe à l’heure actuelle aucun client _desktop_ ou pour la ligne de commande. Le projet que je présente ici vise à combler ce dernier manque — pour la ligne de commande, j’entends ; pour un client _desktop_ graphique, il faudra attendre encore ~~un peu~~ longtemps. _Pebble_ (ou _incenp-pebble_ pour limiter le risque de _name-clash_, _pebble_ étant un nom courant) est donc un client en ligne de commande pour Passman, écrit en Python et libre (licence GPLv3). Il permet de consulter, modifier, ajouter, et supprimer des entrées (*credentials*) dans un coffre (*vault*) Passman.> Ne cherchez aucune logique derrière le nom _Pebble_. Je cherchais juste un nom commençant par P (pour faire un lien, aussi ténu soit-il, avec _Passman_ et _password_), et il se trouve que lorsque j’ai commencé ce projet je travaillais entre autre sur un gène appelé [pebble](https://flybase.org/reports/FBgn0003041), alors voilà... # Démarrage rapide Pebble est disponible sur [PyPI](https://pypi.org/project/incenp.pebble/) et peut donc s’installer en une ligne via `pip` : ```sh $ python -m pip install incenp.pebble ``` Pebble se présente sous la forme d’un programme unique (`pbl`) fournissant un jeu de commandes, à la manière de `git` par exemple, et peut s’utiliser de deux manières : * si une commande est précisée lors de l’invocation initiale (`pbl commande`), la commande indiquée sera exécuté, puis Pebble rendra immédiatement la main ; * si `pbl` est invoqué sans commande, un shell interactif est démarré, à partir duquel plusieurs commandes peuvent être lancées successivement sans jamais quitter le programme. Pebble a besoin d’un fichier de configuration indiquant au minimum comment se connecter au serveur Nextcloud. Le fichier de configuration par défaut est `$XDG_CONFIG_HOME/pebble/config` — un fichier différent peut être indiqué via l’option `-c`. Si le fichier de configuration n’existe pas lorsque Pebble est invoqué, l’utilisatrice est invitée à fournir de quoi créer une configuration minimale: ```sh $ pbl Hostname: nextcloud.example.org Username: alice Password: cpe1704tks ```> Note>> Il est conseillé de créer dans Nextcloud un *mot de passe d’application* qui sera réservé à Pebble, plutôt que d’utiliser le mot de passe principal de son compte Nextcloud. Une fois la configuration créée, on peut alors lister les *credentials* dans le coffre : ```sh pbl> list LinuxFR.org APRIL FSFE Framasoft ``` Puis afficher un *credential* donné (ou plus précisément tous les *credentials* correspondant au motif indiqué) : ```sh pbl> show linux Passphrase for vault MyVault on alice@nextcloud.example.org: +---- LinuxFR.org (1) ---- | URL: https://linuxfr.org/ | Username: alice | Email: alice@example.org | Password: motdepasse123 +---- ``` Pour modifier un *credential*, on utilisera logiquement la commande `edit`, suivie de l’identifiant du *credential* (le *(1)* dans l’exemple ci-dessus). L’éditeur préféré de l’utilisatrice (tel qu’indiqué par la variable d’environnement `EDITOR`, sinon `vim` par défaut) est alors lancé pour permettre l’édition des différents champs, les modifications étant envoyées vers Passman lorsque l’éditeur est fermé. Pour ajouter un *credential*, même principe (avec la commande `add`), sauf que les champs sont initialement vides. # Un peu de technique Cette section présente quelques aspects du fonctionnement de Pebble. Ce n’est pas nécessaire pour _utiliser_ Pebble, c’est juste pour comprendre un peu ce qui se passe en arrière-plan. Pebble étant conçu dès le départ comme un client pour Passman (plutôt que comme un gestionnaire de mots de passe indépendant auquel on aurait ajouté par la suite la synchronisation avec Passman), sans surprise [l’API de Passman](https://github.com/nextcloud/passman/wiki/API) a conditionné une bonne partie de la conception. ## Le cache Pebble obtient de Passman l’intégralité du contenu du _coffre_ (_vault_) sous la forme d’un tableau JSON. Chaque entrée de ce tableau est un dictionnaire représentant un _credential_ comme suit : ```json { "credential_id": 1, "guid": "DBA3A918-DF30-49F9-A64C-A486528EE68C", "user_id": "alice", "vault_id": 3, "label": "LinuxFR", "description": "...encrypted...", "created": 1518182280, "changed": 1518193542, "tags": "...encrypted...", "email": "...encrypted...", "username": "...encrypted...", "password": "encrypted...", "url": "...encrypted...", "icon": null, "renew_interval": null, "expire_time": 0, "delete_time": 0, "files": "...encrypted...", "custom_fields": "...encrypted...", "otp": "...encrypted...", "hidden": 1, "shared_key": null, "compromised": null } ``` Une fois téléchargé, le contenu du coffre est stocké sur disque, dans son format original (JSON donc), sous `$XDG_DATA_HOME/pebble////data`. Toutes les opérations de _lecture_ (lister ou afficher les *credentials*) subséquentes utilisent ce fichier, ces opérations peuvent donc être réalisées hors ligne. Par défaut, ce cache local est rafraîchi auprès du serveur s’il date de plus de vingt-quatre heures. La durée de validité du cache peut être changée via l’option `max_age` dans le fichier de configuration (par exemple, `max_age: 5d` pour un cache expirant après 5 jours) ; on peut aussi forcer un rafraîchissement du cache, ou à l’inverse interdire le rafraîchissement et forcer l’utilisation d’un cache expirée, avec les options `--refresh` ou `--no-refresh`, respectivement. Les opérations d’_écriture_ (ajout, suppression ou modification d’un *credential*) ne passent pas du tout par le cache : elles sont directement envoyées au serveur, _puis_ répercutées dans le cache. Ce mode de fonctionnement a été choisi par simplicité, pour éviter d’avoir à réconcilier deux versions du contenu du coffre (la version en cache et la version du serveur). L’inconvénient évident est que les opérations d’écriture imposent donc un accès au serveur, elles ne sont pas réalisables en mode hors-ligne. ## Chiffrement Comme on peut le voir dans l’exemple ci-dessus, Passman renvoit principalement des données chiffrées, à l’exception de quelques métadonnées qui sont stockées en clair (comme l’étiquette — _label_ — associée à chaque _credential_, ce qui permet de chercher un _credential_ par son étiquette sans avoir à la déchiffrer avant). Ces données sont conservées chiffrées dans le cache local de Pebble, elles ne sont déchiffrées qu’à la demande, juste avant d’afficher le contenu d’un _credential_ (ou de l’envoyer vers l’éditeur pour modification). Le chiffrement utilise le format proposé par la bibliothèque Javascript [SJCL](http://bitwiseshiftleft.github.io/sjcl/) (Stanford Javascript Crypto Library). Brièvement, la fonction `encrypt` de cette bibliothèque prend en entrée un texte clair à chiffrer et un mot de passe, et : * dérive une clef de chiffrement symétrique à partir du mot de passe, avec l’algorithme de dérivation [PBKDF2](https://fr.wikipedia.org/wiki/PBKDF2) ; * chiffre le texte clair avec cette clef, en utilisant par défaut l’algorithme [AES-256](https://fr.wikipedia.org/wiki/Advanced_Encryption_Standard) en [mode CCM](https://en.wikipedia.org/wiki/CCM_mode) ; * encapsule le texte chiffré résultant ainsi que les paramètres requis pour le déchiffrement dans une structure JSON comme ci-dessous : ```json { "v": 1, "salt": "0KezOqk2Yks=", "iter": 1000, "ks": 256, "ts": 64, "iv": "OuObJWWL074phMiuy+YUcw==", "cipher": "aes", "mode": "ccm", "ct": "w9Q6G5gGk0UJ6UJ2/Q==" } ``` * encode la structure JSON produite en base64 et renvoie le résultat. Pour déchiffrer les valeurs contenues dans les _credentials_ renvoyés par Passman, il faut donc procéder en sens inverse : * décoder la chaîne en base64 pour retrouver une structure JSON comme ci-dessus ; * extraire de cette structure les paramètres de déchiffrement ; * dériver la clef de chiffrement à partir des paramètres `salt` (sel), `iter` (nombre d’itérations de PBKDF2), `ks` (taille de la clef à dériver), et du mot de passe fourni par l’utilisatrice ; * déchiffrer le texte chiffré à partir des paramètres `cipher` (algo de chiffrement), `mode` (mode d’opération), `iv` (vecteur d’initialisation), `ts` (taille du tag pour l’algorithme d’authentification), et de la clef dérivée. Pebble confie tout ceci au module python [sjcl](https://github.com/berlincode/sjcl). # Pour en savoir plus Le code est hébergé sur [ma forge personnelle](https://git.incenp.org/damien/pebble). Une copie de la documentation est disponible [en ligne](https://incenp.org/dvlpt/pebble/index.html). La documentation est aussi fournie avec les sources, et peut être trouvée dans le dossier `build/sphinx/html` après avoir été construite avec `python setup.py build_sphinx`.

AltStyle によって変換されたページ (->オリジナル) /