Start pass2keepass script
This commit is contained in:
commit
46e3a00a39
2 changed files with 140 additions and 0 deletions
138
pass2keepass.py
Executable file
138
pass2keepass.py
Executable file
|
@ -0,0 +1,138 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
from getpass import getpass
|
||||
|
||||
import gnupg
|
||||
from pykeepass import PyKeePass
|
||||
|
||||
|
||||
VERBOSE = bool("-v" in sys.argv or "--verbose" in sys.argv)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""Open the a KeePass database, drop the entries and import them from Pass"""
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
usage()
|
||||
sys.exit(1)
|
||||
db_path = sys.argv[1]
|
||||
database = PyKeePass(db_path, getpass(f"Password for {db_path}: "))
|
||||
|
||||
pass_store = PassStore()
|
||||
pass_store.print_tree()
|
||||
drop_kp_database(database)
|
||||
|
||||
|
||||
def drop_kp_database(database: PyKeePass) -> None:
|
||||
"""Remove all groups and entries from a KeePass database"""
|
||||
|
||||
print("Dropping entries...")
|
||||
for entry in database.entries:
|
||||
vprint(f" {entry.title}")
|
||||
entry.delete()
|
||||
|
||||
print("Dropping groups...")
|
||||
for group in database.groups:
|
||||
vprint(f" {group.name}")
|
||||
group.delete()
|
||||
|
||||
|
||||
class PassStore:
|
||||
"""Class to represent a Pass Store"""
|
||||
|
||||
def __init__(self):
|
||||
gpg = gnupg.GPG()
|
||||
self.path = os.path.expanduser(
|
||||
os.environ.get("PASSWORD_STORE_DIR", "~/.password-store")
|
||||
)
|
||||
print(f"Loading Password store at {self.path}...")
|
||||
|
||||
self.groups = [PassGroup("root_group")]
|
||||
|
||||
for item in sorted(os.listdir(self.path)):
|
||||
if item.startswith("."): # .git, .gitignore, .gpg-id, etc.
|
||||
continue
|
||||
if os.path.isfile(os.path.join(self.path, item)):
|
||||
self.groups[0].entries.append(PassEntry(os.path.join(self.path, item)))
|
||||
continue
|
||||
if os.path.isdir(os.path.join(self.path, item)):
|
||||
group = PassGroup(os.path.join(self.path, item))
|
||||
group.trickle_down()
|
||||
self.groups.append(group)
|
||||
continue
|
||||
print(f"Unrecognized item {item}")
|
||||
|
||||
def print_tree(self):
|
||||
"""Print a tree of the store"""
|
||||
|
||||
for group in self.groups:
|
||||
group.print_tree()
|
||||
|
||||
|
||||
class PassGroup:
|
||||
"""Class to represent a Pass Store directory"""
|
||||
|
||||
def __init__(self, path: str):
|
||||
vprint(f"Got group at {path}")
|
||||
self.path = path
|
||||
self.name = os.path.basename(path)
|
||||
self.groups: list[PassGroup] = []
|
||||
self.entries: list[PassEntry] = []
|
||||
|
||||
def trickle_down(self):
|
||||
"""Move down the group to find subgroups and entries"""
|
||||
|
||||
for item in sorted(os.listdir(self.path)):
|
||||
if item.startswith("."): # .git, .gitignore, .gpg-id, etc.
|
||||
continue
|
||||
if os.path.isfile(os.path.join(self.path, item)):
|
||||
self.entries.append(PassEntry(os.path.join(self.path, item)))
|
||||
continue
|
||||
if os.path.isdir(os.path.join(self.path, item)):
|
||||
group = PassGroup(os.path.join(self.path, item))
|
||||
group.trickle_down()
|
||||
self.groups.append(group)
|
||||
continue
|
||||
print(f"Unrecognized item {item}")
|
||||
|
||||
def print_tree(self):
|
||||
"""Print a tree of this group"""
|
||||
|
||||
print(f"{self.name}:")
|
||||
for entry in self.entries:
|
||||
print(f" - {entry.name}")
|
||||
for group in self.groups:
|
||||
group.print_tree()
|
||||
|
||||
|
||||
class PassEntry:
|
||||
"""Class to represent a Pass Store file"""
|
||||
|
||||
def __init__(self, path: str):
|
||||
vprint(f"Got entry at {path}")
|
||||
self.path = path
|
||||
self.name = os.path.basename(path).removesuffix(".gpg")
|
||||
self.group = os.path.basename(os.path.dirname(path))
|
||||
self.password = ""
|
||||
self.username = ""
|
||||
self.url = ""
|
||||
self.notes = ""
|
||||
|
||||
|
||||
def usage():
|
||||
"""Print usage"""
|
||||
|
||||
print(f"Usage: {sys.argv[0]} [-v|--verbose] path_to_database.kdbx", file=sys.stderr)
|
||||
|
||||
|
||||
def vprint(*args, **kwargs):
|
||||
"""Print if VERBOSE is True"""
|
||||
|
||||
if VERBOSE:
|
||||
print(*args, **kwargs)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
gnupg
|
||||
pykeepass
|
Loading…
Reference in a new issue