• [^] # Re: Export des mots de passe

    Posté par . En réponse au journal Migration complète vers Bitwarden à l’aide de rbw. Évalué à 5.

    Oui, j'ai fait un script, méthode La Rache. La variable STORE est à changer, et le résultat est à copier-coller dans l'import générique CSV de l'interface Web de Bitwarden.

    Attention, pass supporte beaucoup de formats différents. À vrai dire, il n'y a même pas de formalisme imposé, ce qui est à la fois une force et une faiblesse. Donc les champs exportés ne seront peut-être pas bons...

    #!/usr/bin/env python3
    import sys
    import pathlib
    import subprocess
    import csv
    from typing import List
    from dataclasses import dataclass
    STORE = "/home/user/.password-store"
    @dataclass
    class PasswordEntry:
     folder: str
     login: str
     password: str
     uris: List[str]
    def parse_passfile(store: pathlib.Path, passfile: pathlib.Path):
     run = subprocess.run(
     [
     "/usr/bin/gpg",
     "--decrypt",
     "--quiet",
     "--yes",
     "--compress-algo=none",
     "--no-encrypt-to",
     store / passfile,
     ],
     text=True,
     capture_output=True,
     )
     if run.returncode != 0:
     print("Decrypting failed")
     return None
     content = run.stdout.splitlines()
     password = content[0]
     uris = []
     login = ""
     folder = ""
     for line in content:
     field_line = line.split(":", 1)
     if len(field_line) == 1:
     continue
     field_name, field_value = [field_line[0].lower(), field_line[1]]
     if field_name in ["password", "pass", "secret"]:
     password = field_value
     elif field_name in ["login", "username", "user"]:
     login = field_value
     elif field_name in ["uri", "url", "website", "site", "link", "launch"]:
     uris.append(field_value)
     if not uris:
     uris = [passfile.stem]
     folder = str(passfile.parent)
     return PasswordEntry(folder, login, password, uris)
    def generate_row(entry: PasswordEntry):
     # folder,favorite,type,name,notes,fields,login_uri,login_username,login_password,login_totp
     return [
     entry.folder,
     "",
     "login",
     entry.uris[0],
     "",
     "",
     entry.uris[0],
     entry.login,
     entry.password,
     "",
     ]
    def iterate_passfile(store_dir: pathlib.Path):
     writer = csv.writer(sys.stdout)
     writer.writerow(
     [
     "folder",
     "favorite",
     "type",
     "name",
     "notes",
     "fields",
     "login_uri",
     "login_username",
     "login_password",
     "login_totp",
     ]
     )
     for passfile in sorted(
     [p.relative_to(store_dir) for p in store_dir.glob("**/*.gpg")]
     ):
     passname = passfile.stem
     dirname = passfile.parent
     entry = parse_passfile(STORE, passfile)
     writer.writerow(generate_row(entry))
    if __name__ == "__main__":
     iterate_passfile(pathlib.Path(STORE))