Example #1
0
class AlteraKeePass:
    def __init__(self, arquivo_kdbx, senha):
        self.kp = PyKeePass(arquivo_kdbx, password=senha)

    def cria_entrada(self, grupo, nome, usuario, senha, url, icone, ip, porta):
        self.group = self.kp.find_groups(name=grupo, first=True)
        self.kp.add_entry(self.group,
                          nome,
                          usuario,
                          senha,
                          url=url,
                          icon=icone)
        self.entry = self.kp.find_entries(title=nome, first=True)
        self.entry.set_custom_property('IP', ip)
        self.entry.set_custom_property('PORT', porta)
        self.kp.save()
Example #2
0
def write_entry(kdbx_file,
                kdbx_password,
                group_path,
                entry_title,
                entry_username,
                entry_password,
                entry_url,
                entry_notes,
                entry_tags,
                kdbx_keyfile=None,
                force_creation=False,
                outfile=None):
    logging.info('Attempt to write entry "{}: {}:{}" to {}'.format(
        entry_title, entry_username, entry_password, group_path))
    samba_db = False
    if kdbx_file.startswith('smb://'):
        samba_db = True
        smb_kdbx_file = smb_retrieve(kdbx_file)
    kp = PyKeePass(smb_kdbx_file if samba_db else kdbx_file,
                   password=kdbx_password,
                   keyfile=kdbx_keyfile)
    dest_group = kp.find_groups_by_path(group_path, first=True)
    kp.add_entry(destination_group=dest_group,
                 title=entry_title,
                 username=entry_username,
                 password=entry_password,
                 url=entry_url,
                 notes=entry_notes,
                 tags=entry_tags,
                 force_creation=force_creation)

    if outfile:
        if outfile.startswith('smb://'):
            file_written = kp.save()
            smb_send(file_written.name, outfile)
            logging.info('Sent database file to {}'.format(outfile))
        else:
            file_written = kp.save(kdbx_file)
            logging.info('KeePass DB written to {}'.format(file_written.name))
    else:
        if samba_db:
            file_written = kp.save()
            smb_send(file_written.name, kdbx_file)
            logging.info('Sent database file to {}'.format(kdbx_file))
        else:
            file_written = kp.save(kdbx_file)
            logging.info('KeePass DB written to {}'.format(file_written.name))
Example #3
0
def keepassxc_new_ssh_key(db_name,
                          db_password,
                          passphrase="",
                          title="",
                          username=""):
    kp = PyKeePass(db_name, password=db_password)

    keyname = title.replace(" ", "-")

    ssh_group = kp.find_groups(name="SSH", first=True)
    if not ssh_group:
        ssh_group = kp.add_group(kp.root_group, "SSH")

    entry = kp.add_entry(ssh_group,
                         title=title,
                         username=username,
                         password=passphrase)

    pub, priv = generate_keys(passphrase)

    entry_ssh_settings = f"""\
<?xml version="1.0" encoding="UTF-16"?>
<EntrySettings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <AllowUseOfSshKey>true</AllowUseOfSshKey>
  <AddAtDatabaseOpen>true</AddAtDatabaseOpen>
  <RemoveAtDatabaseClose>true</RemoveAtDatabaseClose>
  <UseConfirmConstraintWhenAdding>false</UseConfirmConstraintWhenAdding>
  <UseLifetimeConstraintWhenAdding>true</UseLifetimeConstraintWhenAdding>
  <LifetimeConstraintDuration>600</LifetimeConstraintDuration>
  <Location>
    <SelectedType>attachment</SelectedType>
    <AttachmentName>{keyname}</AttachmentName>
    <SaveAttachmentToTempFile>false</SaveAttachmentToTempFile>
  </Location>
</EntrySettings>"""

    attach(kp,
           entry,
           "KeeAgent.settings",
           entry_ssh_settings,
           encoding="utf-16")

    attach(kp, entry, keyname, priv)
    attach(kp, entry, f"{keyname}.pub", pub)

    kp.save()
Example #4
0
def bitwarden_to_keepass(args):
    try:
        kp = PyKeePass(args.database_path,
                       password=args.database_password,
                       keyfile=args.database_keyfile)
    except FileNotFoundError:
        logging.info('KeePass database does not exist, creating a new one.')
        kp = create_database(args.database_path,
                             password=args.database_password,
                             keyfile=args.database_keyfile)
    except CredentialsError as e:
        logging.error(f'Wrong password for KeePass database: {e}')
        return

    folders = subprocess.check_output(
        f'{quote(args.bw_path)} list folders --session {quote(args.bw_session)}',
        shell=True,
        encoding='utf8')
    folders = json.loads(folders)
    groups = {}
    for folder in folders:
        groups[folder['id']] = kp.add_group(kp.root_group, folder['name'])
    logging.info(f'Folders done ({len(groups)}).')

    items = subprocess.check_output(
        f'{quote(args.bw_path)} list items --session {quote(args.bw_session)}',
        shell=True,
        encoding='utf8')
    items = json.loads(items)
    logging.info(f'Starting to process {len(items)} items.')
    for item in items:
        if item['type'] in [ItemTypes.CARD, ItemTypes.IDENTITY]:
            logging.warning(
                f'Skipping credit card or identity item "{item["name"]}".')
            continue

        bw_item = Item(item)

        is_duplicate_title = False
        try:
            while True:
                entry_title = bw_item.get_name(
                ) if not is_duplicate_title else '{name} - ({item_id}'.format(
                    name=bw_item.get_name(), item_id=bw_item.get_id())
                try:
                    entry = kp.add_entry(
                        destination_group=groups[bw_item.get_folder_id()],
                        title=entry_title,
                        username=bw_item.get_username(),
                        password=bw_item.get_password(),
                        notes=bw_item.get_notes())
                    break
                except Exception as e:
                    if 'already exists' in str(e):
                        is_duplicate_title = True
                        continue
                    raise

            totp_secret, totp_settings = bw_item.get_totp()
            if totp_secret and totp_settings:
                entry.set_custom_property('TOTP Seed', totp_secret)
                entry.set_custom_property('TOTP Settings', totp_settings)

            for uri in bw_item.get_uris():
                entry.url = uri['uri']
                break  # todo append additional uris to notes?

            for field in bw_item.get_custom_fields():
                entry.set_custom_property(field['name'], field['value'])

            for attachment in bw_item.get_attachments():
                attachment_tmp_path = f'/tmp/attachment/{attachment["fileName"]}'
                attachment_path = subprocess.check_output(
                    f'{quote(args.bw_path)} get attachment'
                    f' --raw {quote(attachment["id"])} '
                    f'--itemid {quote(bw_item.get_id())} '
                    f'--output {quote(attachment_tmp_path)} --session {quote(args.bw_session)}',
                    shell=True,
                    encoding='utf8').rstrip()
                attachment_id = kp.add_binary(
                    open(attachment_path, 'rb').read())
                entry.add_attachment(attachment_id, attachment['fileName'])
                os.remove(attachment_path)

        except Exception as e:
            logging.warning(
                f'Skipping item named "{item["name"]}" because of this error: {repr(e)}'
            )
            continue

    logging.info('Saving changes to KeePass database.')
    kp.save()
    logging.info('Export completed.')
Example #5
0
def bitwarden_to_keepass(args):
    try:
        kp = PyKeePass(args.database_path,
                       password=args.database_password,
                       keyfile=args.database_keyfile)
    except FileNotFoundError:
        logging.info('KeePass database does not exist, creating a new one.')
        kp = create_database(args.database_path,
                             password=args.database_password,
                             keyfile=args.database_keyfile)
    except CredentialsIntegrityError as e:
        logging.error(f'Wrong password for KeePass database: {e}')
        return

    folders = subprocess.check_output(
        f'{quote(args.bw_path)} list folders --session {quote(args.bw_session)}',
        shell=True,
        encoding='utf8')
    folders = json.loads(folders)
    groups = {}
    for folder in folders:
        groups[folder['id']] = kp.add_group(kp.root_group, folder['name'])
    logging.info(f'Folders done ({len(groups)}).')

    items = subprocess.check_output(
        f'{quote(args.bw_path)} list items --session {quote(args.bw_session)}',
        shell=True,
        encoding='utf8')
    items = json.loads(items)
    logging.info(f'Starting to process {len(items)} items.')
    for item in items:
        if item['type'] == ItemTypes.CARD:
            logging.warning(f'Skipping credit card item "{item["name"]}".')
            continue

        bw_item = Item(item)

        e = kp.add_entry(groups[bw_item.get_folder_id()],
                         title=bw_item.get_name(),
                         username=bw_item.get_username(),
                         password=bw_item.get_password(),
                         notes=bw_item.get_notes())

        totp_secret, totp_settings = bw_item.get_totp()
        if totp_secret and totp_settings:
            e.set_custom_property('TOTP Seed', totp_secret)
            e.set_custom_property('TOTP Settings', totp_settings)

        for uri in bw_item.get_uris():
            e.url = uri['uri']
            break  # todo append additional uris to notes?

        for field in bw_item.get_custom_fields():
            e.set_custom_property(str(field['name']), field['value'])

        for attachment in bw_item.get_attachments():
            attachment_tmp_path = f'./attachment_tmp/{attachment["fileName"]}'
            attachment_path = subprocess.check_output(
                f'{quote(args.bw_path)} get attachment'
                f' --raw {quote(attachment["id"])} '
                f'--itemid {quote(bw_item.get_id())} '
                f'--output {quote(attachment_tmp_path)} --session {quote(args.bw_session)}',
                shell=True,
                encoding='utf8').rstrip()
            attachment_id = kp.add_binary(open(attachment_path, 'rb').read())
            e.add_attachment(attachment_id, attachment['fileName'])
            os.remove(attachment_path)

    logging.info('Saving changes to KeePass database.')
    kp.save()
    logging.info('Export completed.')
Example #6
0
# load database
kp = PyKeePass(dbfile, password=os.environ['PASSWORD'])
group = kp.find_groups(name=groupname, first=True)

count = 1
with open(tempfile, "r") as rd:
    # Read lines in loop
    for line in rd:
        # All lines (besides the last) will include  newline, so strip it
        data = line.strip()
        data = data.split(';;;')

        if len(data) != 4:
            print("Fehlerhafte Eingabe! Zeile: " + str(count))
            print(data)
            sys.exit()

        # Variablen setzen
        title = str(data[0])
        user = str(data[1])
        password = str(data[2])
        notes = str(data[3])

        # Eintrag in KeePassDB schreiben (temporär, nicht gespeichert)
        kp.add_entry(group, title, user, password, None, notes)
        count += 1

kp.save()

sys.exit()
def main(input_file, target_file, password):
    def matches(query, card):
        try:
            if query is None:
                return True

            query = query.lower()
            if query in card['@title'].lower():
                return True

            # for field in card['field']:
            #     if query in field['@name'].lower():
            #         return True

            #     if '#text' in field and query in field['#text'].lower():
            #         return True
        except:
            pass

        return False

    if len(sys.argv) == 2:
        search = sys.argv[1]
    else:
        search = None

    db = Decrypter(input_file, password)
    kp = PyKeePass('New3.kdbx', password='******')
    kp.root_group.name = "test_title"
    kp.password = password
    entries = []
    try:
        xml = db.decrypt()
        xml = parseString(xml)
    except:
        print("cannot decrypt, maybe wrong password?")
        sys.exit(1)

    for node in xml.getElementsByTagName('card'):
        is_template = False
        if node.hasAttribute('template'):
            is_template = (node.attributes['template'].value == 'true')

        if not is_template:
            entries.append(Entry(node))

    duplicate_check = set()
    for entry in entries:

        password = ""
        login = ""
        url = ""
        notes = ""
        # extract all types the fields and their value
        type_value = {
            entry.fields[x].type: entry.fields[x].value
            for x in entry.fields
        }
        # map the type of the field in safeincloud to the field type in pykeepass
        map_types = {
            "password": "******",
            "login": "******",
            "website": "url",
            "notes": "notes"
        }
        # username and password are required fields
        mapped_type_value = {"username": "", "password": ""}
        # add all other fields with the new names
        mapped_type_value.update({
            map_types[x]: type_value[x]
            for x in type_value if x in map_types
        })

        # ensure that the title is unique
        title = entry.title
        if title in duplicate_check:
            i = 2
            while title + str(i) in duplicate_check:
                i = i + 1
            title = title + str(i)
            assert title not in duplicate_check

        # add entry to keepass file
        kp.add_entry(kp.root_group, title, **mapped_type_value)
        # add title to duplicate check
        duplicate_check.add(title)

    kp.save(target_file)
    print("file successful mapped")
Example #8
0
from pykeepass import PyKeePass
# load database
kp = PyKeePass(r'C:\Users\danie\Git\ansible\ansible_home\test_db.kdbx',
               password='******')
group = kp.groups
#kp.add_entry(destination_group='test_db',title='testentry', username='******', password='******')
#kp.add_group(kp.root_group, 'test_addgroup')
kp.add_entry(destination_group=group[2],
             title='testentry',
             username='******',
             password='******')
kp.save()
print('ende')
Example #9
0
class DatabaseManager:
    logging_manager = NotImplemented
    db = NotImplemented
    database_path = ""
    password_try = ""
    password_check = ""
    password = ""
    keyfile_hash = NotImplemented
    changes = False
    save_running = False
    scheduled_saves = 0
    database_file_descriptor = NotImplemented

    def __init__(self,
                 database_path,
                 password=None,
                 keyfile=None,
                 logging_manager=None):
        self.logging_manager = logging_manager
        self.db = PyKeePass(database_path, password, keyfile)
        self.database_path = database_path
        self.database_file_descriptor = Gio.File.new_for_path(database_path)
        self.password = password

    #
    # Group Transformation Methods
    #

    # Return the parent group object from the child group uuid
    def get_group_parent_group_from_uuid(self, uuid):
        group = self.db.find_groups(uuid=uuid, first=True)
        return group.parentgroup

    # Return the parent group object from the child group object
    def get_group_parent_group_from_object(self, group):
        return group.parentgroup

    # Return the belonging group object for a group uuid
    def get_group_object_from_uuid(self, uuid):
        return self.db.find_groups(uuid=uuid, first=True)

    # Return the belonging group name for a group uuid
    def get_group_name_from_uuid(self, uuid):
        group = self.db.find_groups(uuid=uuid, first=True)
        return self.get_group_name_from_group_object(group)

    # Return the path for a group object
    def get_group_path_from_group_object(self, group):
        return group.path

    # Return the belonging group uuid for a group object
    def get_group_uuid_from_group_object(self, group):
        return group.uuid

    # Return the belonging name for a group object
    def get_group_name_from_group_object(self, group):
        if group.name is None:
            return ""
        else:
            return group.name

    # Return the belonging notes for a group object
    def get_group_notes_from_group_object(self, group):
        if group.notes is None:
            return ""
        else:
            return group.notes

    # Return the belonging icon for a group object
    def get_group_icon_from_group_object(self, group):
        return group.icon

    # Return the belonging notes for a group uuid
    def get_group_notes_from_group_uuid(self, uuid):
        group = self.db.find_groups(uuid=uuid, first=True)
        return self.get_group_notes_from_group_object(group)

    # Return path for group uuid
    def get_group_path_from_group_uuid(self, uuid):
        group = self.db.find_groups(uuid=uuid, first=True)
        return group.path

    #
    # Entry Transformation Methods
    #

    # Return the belonging entry object for a entry uuid
    def get_entry_object_from_uuid(self, uuid):
        return self.db.find_entries(uuid=uuid, first=True)

    # Return entry uuid from entry object
    def get_entry_uuid_from_entry_object(self, entry):
        return entry.uuid

    # Return parent group from entry uuid
    def get_entry_parent_group_from_uuid(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        return entry.parentgroup

    # Return parent group from entry object
    def get_entry_parent_group_from_entry_object(self, entry):
        return entry.parentgroup

    # Return the belonging name for an entry object
    def get_entry_name_from_entry_object(self, entry):
        if entry.title is None:
            return ""
        else:
            return entry.title

    # Return entry name from entry uuid
    def get_entry_name_from_entry_uuid(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        return self.get_entry_name_from_entry_object(entry)

    # Return the belonging icon for an entry object
    def get_entry_icon_from_entry_object(self, entry):
        return entry.icon

    # Return entry icon from entry uuid
    def get_entry_icon_from_entry_uuid(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        return entry.icon

    # Return the belonging username for an entry object
    def get_entry_username_from_entry_object(self, entry):
        if entry.username is None:
            return ""
        else:
            return entry.username

    # Return the belonging username for an entry uuid
    def get_entry_username_from_entry_uuid(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        return self.get_entry_username_from_entry_object(entry)

    # Return the belonging password for an entry object
    def get_entry_password_from_entry_object(self, entry):
        if entry.password is None:
            return ""
        else:
            return entry.password

    # Return the belonging password for an entry uuid
    def get_entry_password_from_entry_uuid(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        return self.get_entry_password_from_entry_object(entry)

    # Return the belonging url for an entry uuid
    def get_entry_url_from_entry_uuid(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        return self.get_entry_url_from_entry_object(entry)

    # Return the belonging url for an entry object
    def get_entry_url_from_entry_object(self, entry):
        if entry.url is None:
            return ""
        else:
            return entry.url

    # Return the belonging notes for an entry uuid
    def get_entry_notes_from_entry_uuid(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        return entry.notes

    # Return the belonging notes for an entry object
    def get_entry_notes_from_entry_object(self, entry):
        if entry.notes is None:
            return ""
        else:
            return entry.notes

    # Return the beloging expiry date for an entry uuid
    def get_entry_expiry_date_from_entry_uuid(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        return entry.expiry_time

    # Return the beloging expiry date for an entry object
    def get_entry_expiry_date_from_entry_object(self, entry):
        return entry.expiry_time

    # Return the belonging color for an entry uuid
    def get_entry_color_from_entry_uuid(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        if entry.get_custom_property("color_prop_LcljUMJZ9X") is None:
            return "NoneColorButton"
        else:
            return entry.get_custom_property("color_prop_LcljUMJZ9X")

    # Return the belonging value for an attribute
    def get_entry_attribute_value_from_entry_uuid(self, uuid, key):
        entry = self.db.find_entries(uuid=uuid, first=True)
        if entry.get_custom_property(key) is None:
            return ""
        else:
            return entry.get_custom_property(key)

    # Return all attributes for an entry uuid
    def get_entry_attributes_from_entry_uuid(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        return entry.custom_properties

    # Return all attributes for an entry object
    def get_entry_attributes_from_entry_object(self, entry):
        return entry.custom_properties

    #
    # Entry Checks
    #

    def has_entry_name(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        if entry.title is None:
            return False
        else:
            return True

    def has_entry_username(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        if entry.username is None:
            return False
        else:
            return True

    def has_entry_password(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        if entry.password is None:
            return False
        else:
            return True

    def has_entry_url(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        if entry.url is None:
            return False
        else:
            return True

    def has_entry_notes(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        if entry.notes is None:
            return False
        else:
            return True

    def has_entry_icon(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        if entry.icon is None:
            return False
        else:
            return True

    def has_entry_expiry_date(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        return entry.expires

    def has_entry_expired(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        if entry.expired is False:
            return False
        else:
            return True

    def has_entry_color(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        if entry.get_custom_property(
                "color_prop_LcljUMJZ9X") is None or entry.get_custom_property(
                    "color_prop_LcljUMJZ9X") == "NoneColorButton":
            return False
        else:
            return True

    def has_entry_attributes(self, uuid):
        entry = self.db.find_entries(uuid=uuid, first=True)
        if len(entry.custom_properties) == 0:
            return False
        else:
            return True

    def has_entry_attribute(self, uuid, key):
        entry = self.db.find_entries(uuid=uuid, first=True)
        if entry.get_custom_property(key) is None:
            return False
        else:
            return True

    #
    # Group Checks
    #

    def has_group_name(self, uuid):
        group = self.db.find_groups(uuid=uuid, first=True)
        if group.name is None:
            return False
        else:
            return True

    def has_group_notes(self, uuid):
        group = self.db.find_groups(uuid=uuid, first=True)
        if group.notes is None:
            return False
        else:
            return True

    def has_group_icon(self, uuid):
        group = self.db.find_groups(uuid=uuid, first=True)
        if group.icon is None:
            return False
        else:
            return True

    #
    # Database Modifications
    #

    # Add new group to database
    def add_group_to_database(self, name, icon, notes, parent_group):
        group = self.db.add_group(parent_group, name, icon=icon, notes=notes)
        self.changes = True
        self.set_element_mtime(parent_group)

        return group

    # Delete a group
    def delete_group_from_database(self, group):
        self.db.delete_group(group)
        self.changes = True
        if group.parentgroup is not None:
            self.set_element_mtime(group.parentgroup)

    # Add new entry to database
    def add_entry_to_database(self, name, username, password, url, notes, icon,
                              group_uuid):
        destination_group = self.get_group_object_from_uuid(group_uuid)
        entry = self.db.add_entry(
            destination_group,
            name,
            username,
            password,
            url=url,
            notes=notes,
            expiry_time=None,
            tags=None,
            icon=icon,
            force_creation=self.check_entry_in_group_exists(
                "", destination_group))
        self.changes = True
        self.set_element_mtime(destination_group)

        return entry

    # Delete an entry
    def delete_entry_from_database(self, entry):
        self.db.delete_entry(entry)
        self.changes = True
        if entry.parentgroup is not None:
            self.set_element_mtime(entry.parentgroup)

    # Duplicate an entry
    def duplicate_entry(self, entry):
        title = entry.title
        if title is None:
            title = ""

        username = entry.username
        if username is None:
            username = ""

        password = entry.password
        if password is None:
            password = ""

        # NOTE: With clone is meant a duplicated object, not the process of cloning/duplication; "the" clone
        clone_entry = self.db.add_entry(entry.parentgroup,
                                        title + " - " + _("Clone"),
                                        username,
                                        password,
                                        url=entry.url,
                                        notes=entry.notes,
                                        expiry_time=entry.expiry_time,
                                        tags=entry.tags,
                                        icon=entry.icon,
                                        force_creation=True)

        # Add custom properties
        for key in entry.custom_properties:
            value = entry.custom_properties[key]
            if value is None:
                value = ""
            clone_entry.set_custom_property(key, value)

        self.changes = True
        if entry.parentgroup is not None:
            self.set_element_mtime(entry.parentgroup)

    # Write all changes to database
    def save_database(self):
        if self.save_running is False and self.changes is True:
            self.save_running = True

            kdbx = KDBX.build(self.db.kdbx,
                              password=self.db.password,
                              keyfile=self.db.keyfile)

            try:
                output_stream = self.database_file_descriptor.replace(
                    None, False, Gio.FileCreateFlags.REPLACE_DESTINATION
                    | Gio.FileCreateFlags.PRIVATE, None)
                output_stream.write_all(kdbx)
                output_stream.close()
                self.logging_manager.debug("Saved database")
                self.changes = False
            except Exception:
                self.logging_manager.error(
                    "Error occured while saving database")

            # Workaround
            # Fix created and proposed: https://github.com/pschmitt/pykeepass/pull/102
            self.db.kdbx = KDBX.parse_file(self.db.filename,
                                           password=self.db.password,
                                           keyfile=self.db.keyfile)

            self.save_running = False

    # Set database password
    def set_database_password(self, new_password):
        self.db.password = new_password
        self.changes = True

    # Set database keyfile
    def set_database_keyfile(self, new_keyfile):
        self.db.keyfile = new_keyfile
        self.changes = True

    #
    # Entry Modifications
    #

    def set_entry_name(self, uuid, name):
        entry = self.db.find_entries(uuid=uuid, first=True)
        entry.title = name
        self.changes = True
        self.set_element_mtime(entry)

    def set_entry_username(self, uuid, username):
        entry = self.db.find_entries(uuid=uuid, first=True)
        entry.username = username
        self.changes = True
        self.set_element_mtime(entry)

    def set_entry_password(self, uuid, password):
        entry = self.db.find_entries(uuid=uuid, first=True)
        entry.password = password
        self.changes = True
        self.set_element_mtime(entry)

    def set_entry_url(self, uuid, url):
        entry = self.db.find_entries(uuid=uuid, first=True)
        entry.url = url
        self.changes = True
        self.set_element_mtime(entry)

    def set_entry_notes(self, uuid, notes):
        entry = self.db.find_entries(uuid=uuid, first=True)
        entry.notes = notes
        self.changes = True
        self.set_element_mtime(entry)

    def set_entry_icon(self, uuid, icon):
        entry = self.db.find_entries(uuid=uuid, first=True)
        entry.icon = icon
        self.changes = True
        self.set_element_mtime(entry)

    def set_entry_expiry_date(self, uuid, date):
        entry = self.db.find_entries(uuid=uuid, first=True)
        entry.expiry_time = date
        entry.expires
        self.changes = True
        self.set_element_mtime(entry)

    def set_entry_color(self, uuid, color):
        entry = self.db.find_entries(uuid=uuid, first=True)
        entry.set_custom_property("color_prop_LcljUMJZ9X", color)
        self.changes = True
        self.set_element_mtime(entry)

    def set_entry_attribute(self, uuid, key, value):
        entry = self.db.find_entries(uuid=uuid, first=True)
        entry.set_custom_property(key, value)
        self.changes = True
        self.set_element_mtime(entry)

    def delete_entry_attribute(self, uuid, key):
        entry = self.db.find_entries(uuid=uuid, first=True)
        entry.delete_custom_property(key)
        self.changes = True
        self.set_element_mtime(entry)

    # Move an entry to another group
    def move_entry(self, uuid, destination_group_object):
        entry = self.db.find_entries(uuid=uuid, first=True)
        self.db.move_entry(entry, destination_group_object)
        if entry.parentgroup is not None:
            self.set_element_mtime(entry.parentgroup)
        self.set_element_mtime(destination_group_object)

    def set_element_ctime(self, element):
        element.ctime = datetime.utcnow()

    def set_element_atime(self, element):
        element.atime = datetime.utcnow()

    def set_element_mtime(self, element):
        element.mtime = datetime.utcnow()

    #
    # Group Modifications
    #

    def set_group_name(self, uuid, name):
        group = self.db.find_groups(uuid=uuid, first=True)
        group.name = name
        self.changes = True
        self.set_element_mtime(group)

    def set_group_notes(self, uuid, notes):
        group = self.db.find_groups(uuid=uuid, first=True)
        group.notes = notes
        self.set_element_mtime(group)

    def set_group_icon(self, uuid, icon):
        group = self.db.find_groups(uuid=uuid, first=True)
        group.icon = icon
        self.set_element_mtime(group)

    # Move an group
    def move_group(self, uuid, destination_group_object):
        group = self.db.find_groups(uuid=uuid, first=True)
        self.db.move_group(group, destination_group_object)
        if group.parentgroup is not None:
            self.set_element_mtime(group.parentgroup)
        self.set_element_mtime(destination_group_object)

    #
    # Read Database
    #

    def get_groups_in_root(self):
        return self.db.root_group.subgroups

    # Return list of all groups in folder
    def get_groups_in_folder(self, uuid):
        folder = self.get_group_object_from_uuid(uuid)
        return folder.subgroups

    # Return list of all entries in folder
    def get_entries_in_folder(self, uuid):
        parent_group = self.get_group_object_from_uuid(uuid)
        return parent_group.entries

    # Return the database filesystem path
    def get_database(self):
        return self.database_path

    # Return the root group of the database instance
    def get_root_group(self):
        return self.db.root_group

    # Check if root group
    def check_is_root_group(self, group):
        if group.is_root_group:
            return True
        else:
            return False

    # Check if entry with title in group exists
    def check_entry_in_group_exists(self, title, group):
        entry = self.db.find_entries(title=title,
                                     group=group,
                                     recursive=False,
                                     history=False,
                                     first=True)
        if entry is None:
            return False
        else:
            return True

    # Search for an entry or a group
    def search(self, string, fulltext, global_search=True, path=None):
        uuid_list = []

        if fulltext is False:
            for group in self.db.find_groups(name="(?i)" +
                                             string.replace(" ", ".*"),
                                             recursive=global_search,
                                             path=path,
                                             regex=True):
                if group.is_root_group is False:
                    uuid_list.append(group.uuid)
        else:
            for group in self.db.groups:
                if group.is_root_group is False and group.uuid not in uuid_list:
                    if string.lower(
                    ) in self.get_group_notes_from_group_object(group):
                        uuid_list.append(group.uuid)

        if fulltext is False:
            for entry in self.db.find_entries(title="(?i)" +
                                              string.replace(" ", ".*"),
                                              recursive=global_search,
                                              path=path,
                                              regex=True):
                uuid_list.append(entry.uuid)
        else:
            for entry in self.db.entries:
                if entry.uuid not in uuid_list:
                    if string.lower(
                    ) in self.get_entry_username_from_entry_object(entry):
                        uuid_list.append(entry.uuid)
                    elif string.lower(
                    ) in self.get_entry_notes_from_entry_object(entry):
                        uuid_list.append(entry.uuid)

        return uuid_list

    # Check if object is group
    def check_is_group(self, uuid):
        if self.get_group_object_from_uuid(uuid) is None:
            return False
        else:
            return True

    def check_is_group_object(self, group):
        return hasattr(group, "name")

    #
    # Properties
    #

    def get_element_creation_date(self, element):
        if element.ctime is not None:
            local_timestamp = element.ctime.astimezone(tz.tzlocal())
            timestamp = GLib.DateTime.new_local(
                int(datetime.strftime(local_timestamp, "%Y")),
                int(datetime.strftime(local_timestamp, "%m")),
                int(datetime.strftime(local_timestamp, "%d")),
                int(datetime.strftime(local_timestamp, "%H")),
                int(datetime.strftime(local_timestamp, "%M")),
                float(datetime.strftime(local_timestamp, "%S")))
            return timestamp.format("%c")
        else:
            return "-"

    def get_element_acessed_date(self, element):
        if element.atime is not None:
            local_timestamp = element.atime.astimezone(tz.tzlocal())
            timestamp = GLib.DateTime.new_local(
                int(datetime.strftime(local_timestamp, "%Y")),
                int(datetime.strftime(local_timestamp, "%m")),
                int(datetime.strftime(local_timestamp, "%d")),
                int(datetime.strftime(local_timestamp, "%H")),
                int(datetime.strftime(local_timestamp, "%M")),
                float(datetime.strftime(local_timestamp, "%S")))
            return timestamp.format("%c")
        else:
            return "-"

    def get_element_modified_date(self, element):
        if element.mtime is not None:
            local_timestamp = element.mtime.astimezone(tz.tzlocal())
            timestamp = GLib.DateTime.new_local(
                int(datetime.strftime(local_timestamp, "%Y")),
                int(datetime.strftime(local_timestamp, "%m")),
                int(datetime.strftime(local_timestamp, "%d")),
                int(datetime.strftime(local_timestamp, "%H")),
                int(datetime.strftime(local_timestamp, "%M")),
                float(datetime.strftime(local_timestamp, "%S")))
            return timestamp.format("%c")
        else:
            return "-"

    #
    # Database creation methods
    #

    # Set the first password entered by the user (for comparing reasons)
    def set_password_try(self, password):
        self.password_try = password

    # Set the second password entered by the user (for comparing reasons)
    def set_password_check(self, password):
        self.password_check = password

    # Compare the first password entered by the user with the second one
    def compare_passwords(self):
        if self.password_try == self.password_check:
            if self.password_try == "" and self.password_check == "":
                return False
            else:
                return True
        else:
            return False

    # Create keyfile hash
    def create_keyfile_hash(self, keyfile_path):
        hasher = hashlib.sha512()
        with open(keyfile_path, 'rb') as file:
            buffer = 0
            while buffer != b'':
                buffer = file.read(1024)
                hasher.update(buffer)
        return hasher.hexdigest()

    # Set keyfile hash
    def set_keyfile_hash(self, keyfile_path):
        self.keyfile_hash = self.create_keyfile_hash(keyfile_path)

    # Get changes
    def made_database_changes(self):
        return self.changes

    def parent_checker(self, current_group, moved_group):
        if current_group.is_root_group:
            return False
        elif current_group.uuid == moved_group.uuid:
            return True
        else:
            return self.parent_checker(current_group.parentgroup, moved_group)

    def get_database_encryption(self):
        return self.db.encryption_algorithm

    def get_database_derivation(self):
        return self.db.version
#!/usr/bin/env python3

from pykeepass import PyKeePass
from ruamel.yaml import YAML

yaml = YAML()

with open('environments/secrets.yml') as fp:
    secrets = yaml.load(fp)

kp = PyKeePass('secrets/keepass.kdbx', password='******')

# FIXME(berendt): use attachments
kp.add_entry(kp.root_group, 'SSH Keypair Configuration',
             username='',
             password=secrets.get('configuration_git_private_key'))
kp.add_entry(kp.root_group, 'SSH Keypair Operator',
             username='',
             password=secrets.get('operator_private_key'))

try:
    with open('secrets/vaultpass') as fp:
        vaultpass = fp.read()

    kp.add_entry(kp.root_group, 'Ansible Vault',
                 username='', password=vaultpass)

# NOTE: If Ansible Vault is not used, the file does not exist.
except FileNotFoundError:
    pass
Example #11
0
class KeepassLoader:

    kp = NotImplemented
    database_path = ""
    password_try = ""
    password_check = ""
    password = ""
    group_list = []

    def __init__(self, database_path, password):
        self.kp = PyKeePass(database_path, password)
        self.database_path = database_path

    def add_group(self, name, icon, note, parent_group):
        group = Group(name, icon, note, parent_group)
        self.kp.add_group(group.get_parent_group(), group.get_name())
        self.group_list.append(group)

    def add_entry(self, group_path, entry_name, username, password, url, notes,
                  icon):
        entry = Entry(group_path, entry_name, username, password, url, notes,
                      icon)
        self.kp.add_entry(self.kp.find_groups_by_path(entry.get_group_path()),
                          entry.get_entry_name(),
                          entry.get_username(),
                          entry.get_password(),
                          url=entry.get_url(),
                          notes=entry.get_notes(),
                          icon=entry.get_icon())

    def get_entries(self, group_path):
        group = self.kp.find_groups_by_path(group_path, first=True)
        #group = self.kp.find_groups(name="Untergruppe", first=True)
        print(group)
        print(group.entries)
        entry_list = []
        for entry in group.entries:
            entry_list.append(
                Entry(group, entry.title, entry.username, entry.password,
                      entry.url, entry.notes, entry.icon))
        return entry_list

    def get_groups(self):
        group_list = []
        groups = self.kp.groups
        for group in groups:
            if group.path != "/":
                group_list.append(
                    Group(group.name,
                          group.path,
                          icon=group.icon,
                          notes="",
                          parent_group=group.parent_group))
        return group_list

    #we wanted to turn off the automatic saving after each action and connect it instead to a button
    def save(self):
        self.kp.save()

    #this method sets the initial password for the newly created database
    def set_database_password(self, new_password):
        self.kp.set_credentials(new_password)
        self.save()

    #this method changes the password of existing database (therefore the old password must be typed in to prevent others changing your password)
    def change_database_password(self, old_password, new_password):
        if self.password == old_password:
            self.kp.set_credentials(new_password)
            self.save()

    #
    # Return the database filesystem path
    #

    def get_database(self):
        print(self.database_path)
        return self.database_path

    #
    # Return the root group of the database instance
    #

    def get_root_group(self):
        return self.kp.root_group

    #
    # Set the first password entered by the user (for comparing reasons)
    #

    def set_password_try(self, password):
        self.password_try = password

    #
    # Set the second password entered by the user (for comparing reasons)
    #

    def set_password_check(self, password):
        self.password_check = password

    #
    # Compare the first password entered by the user with the second one
    #

    def compare_passwords(self):
        if self.password_try == self.password_check:
            if self.password_try == "" and self.password_check == "":
                return False
            else:
                return True
        else:
            return False
Example #12
0
            if arg == '--create':
                CREATE = True

            if arg == '--title':
                KEEPASSTITEL = sys.argv[idx+1]
            
            if arg == '--username':
                KEEPASSUSERNAME = sys.argv[idx+1]

            if arg == "--count":
                if (len(sys.argv) > idx+1):
                  pwdlength = sys.argv[idx+1]
                else:
                    print(f"ERROR: count value is missing using default value: {pwdlength}")


        if (CREATE):
          password = password_generator(int(pwdlength))
          if (DISPLAYPWD):
            print(password)          
          clipboard.copy(password)
          if (KEEPASSWRITE):
              group = kp.find_groups(name=KEEPASSDEFAULTGRP, first=True)
              kp.add_entry(group, str(KEEPASSTITEL), str(KEEPASSUSERNAME), str(password))
              kp.save()
              if (config['DEFAULT']['VAULTENABLE']== 'Y'):
                client.write(str(config['DEFAULT']['VAULTKV'] + KEEPASSTITEL),
                    username = KEEPASSUSERNAME,
                    password = password,
                    )
Example #13
0
class P2KP2:
    """Convert a Pass db into a Keepass2 one."""

    db: PyKeePass

    def __init__(self,
                 password: str,
                 destination: str = None,
                 overwrite: bool = False):
        """Constructor for P2KP2

        :param password: the password for the new Keepass db
        :param destination: the final db path
        :param overwrite: force writing over existing database
        """
        if destination is None:
            destination = "pass.kdbx"
        if not os.path.exists(destination) or overwrite:
            copyfile(empty_db_path, destination)
        else:
            raise DbAlreadyExistsException()
        self.db = PyKeePass(destination)
        self.db.password = password
        self.db.save()
        self.event_stream = Subject()

    def populate_db(self, pass_reader: PassReader):
        """Populate the keepass db with data from the PassReader."""
        i = 0
        for pass_entry in pass_reader.entries:
            self.add_entry(pass_entry)
            i = i + 1
            self.event_stream.on_next(i)
        self.db.save()

    def add_entry(self, pass_entry: PassEntry) -> Entry:
        """Add a keepass entry to the db containing all data from the relative pass entry. Create the group if needed.

        :param pass_entry: the original pass entry
        :return: the newly added keepass entry
        """
        # find the correct group for the entry. If not there, create it
        entry_group = self.db.root_group  # start from the root group
        if len(pass_entry.groups) > 0:
            for group_name in pass_entry.groups:
                # since pass folder names are unique, the possible first result is also the only one
                group = self.db.find_groups(name=group_name,
                                            recursive=False,
                                            group=entry_group,
                                            first=True)
                if group is None:
                    # the group is not already there, let's create it
                    group = self.db.add_group(destination_group=entry_group,
                                              group_name=group_name)
                entry_group = group
        # create the entry, setting group, title, user and pass
        entry = self.db.add_entry(entry_group, pass_entry.title,
                                  pass_entry.user, pass_entry.password)
        # set the url and the notes
        entry.url = pass_entry.url
        entry.notes = pass_entry.notes
        # add all custom fields
        for pass_entry, value in pass_entry.custom_properties.items():
            entry.set_custom_property(pass_entry, value)
        return entry
Example #14
0
    print("Modo de empleo: {} <input.geco>")
    sys.exit()

input_file = sys.argv[1]
output_file = 'db.kdbx'
master = getpass.getpass("Contraseña maestra: ")

aes = CustomAES()
kp = PyKeePass('database.kdbx', password="******")
kp.password = master

groups = {}

with open(input_file, 'r') as f:
    for p in f.readlines():
        name, type, description, account, password, cypher_method, updated, expiration = p.split("|")
        expiration = datetime.datetime.fromtimestamp(float(expiration))
        updated = datetime.datetime.fromtimestamp(float(updated))
        name, type, description, account =\
                map(lambda x: x.replace("\\n", "\n"), (name, type, description, account))

        clear = aes.decrypt(password, master)

        if type and not type in groups:
            group = kp.add_group(kp.root_group, type)
            groups[type] = group
        group = groups.get(type, kp.root_group)

        kp.add_entry(group, name, account, clear, notes=description)
    kp.save(output_file)
def bitwarden_to_keepass(args):
    try:
        kp = PyKeePass(args.database_path,
                       password=args.database_password,
                       keyfile=args.database_keyfile)
    except FileNotFoundError:
        logging.info('KeePass database does not exist, creating a new one.')
        kp = create_database(args.database_path,
                             password=args.database_password,
                             keyfile=args.database_keyfile)
    except CredentialsError as e:
        logging.error(f'Wrong password for KeePass database: {e}')
        return

    folders = subprocess.check_output(
        f'{quote(args.bw_path)} list folders --session {quote(args.bw_session)}',
        shell=True,
        encoding='utf8')
    folders = json.loads(folders)
    # sort folders so that in the case of nested folders, the parents would be guaranteed to show up before the children
    folders.sort(key=lambda x: x['name'])
    groups_by_id = {}
    groups_by_name = {}
    for folder in folders:
        # entries not associated with a folder should go under the root group
        if folder['id'] is None:
            groups_by_id[folder['id']] = kp.root_group
            continue

        parent_group = kp.root_group
        target_name = folder['name']

        # check if this is a nested folder; set appropriate parent group if so
        folder_path_split = target_name.rsplit('/', maxsplit=1)
        if len(folder_path_split) > 1:
            parent_group = groups_by_name[folder_path_split[0]]
            target_name = folder_path_split[1]

        new_group = kp.add_group(parent_group, target_name)

        groups_by_id[folder['id']] = new_group
        groups_by_name[folder['name']] = new_group
    logging.info(f'Folders done ({len(groups_by_id)}).')

    items = subprocess.check_output(
        f'{quote(args.bw_path)} list items --session {quote(args.bw_session)}',
        shell=True,
        encoding='utf8')
    items = json.loads(items)
    logging.info(f'Starting to process {len(items)} items.')
    for item in items:
        bw_item = Item(item)

        is_duplicate_title = False
        try:
            while True:
                entry_title = bw_item.get_name(
                ) if not is_duplicate_title else '{name} - ({item_id}'.format(
                    name=bw_item.get_name(), item_id=bw_item.get_id())
                try:
                    entry = kp.add_entry(destination_group=groups_by_id[
                        bw_item.get_folder_id()],
                                         title=entry_title,
                                         username=bw_item.get_username(),
                                         password=bw_item.get_password(),
                                         notes=bw_item.get_notes())
                    break
                except Exception as e:
                    if 'already exists' in str(e):
                        is_duplicate_title = True
                        continue
                    raise

            totp_secret, totp_settings = bw_item.get_totp()
            if totp_secret and totp_settings:
                entry.set_custom_property('TOTP Seed', totp_secret)
                entry.set_custom_property('TOTP Settings', totp_settings)

            for uri in bw_item.get_uris():
                entry.url = uri['uri']
                break  # todo append additional uris to notes?

            for field in bw_item.get_custom_fields():
                entry.set_custom_property(field['name'], field['value'])

            for card_field_name, card_field_val in bw_item.get_card().items():
                if card_field_val is not None:
                    entry.set_custom_property(
                        f"{CUSTOM_FIELD_PREFIX}_CARD_{card_field_name}",
                        card_field_val)

            for identity_field_name, identity_field_val in bw_item.get_identity(
            ).items():
                if identity_field_val is not None:
                    entry.set_custom_property(
                        f"{CUSTOM_FIELD_PREFIX}_IDENTITY_{identity_field_name}",
                        identity_field_val)

            for attachment in bw_item.get_attachments():
                attachment_tmp_path = f'{args.tmp_path}/attachment/{attachment["fileName"]}'
                attachment_path = subprocess.check_output(
                    f'{quote(args.bw_path)} get attachment'
                    f' --raw {quote(attachment["id"])} '
                    f'--itemid {quote(bw_item.get_id())} '
                    f'--output {quote(attachment_tmp_path)} --session {quote(args.bw_session)}',
                    shell=True,
                    encoding='utf8').rstrip()
                attachment_id = kp.add_binary(
                    open(attachment_path, 'rb').read())
                entry.add_attachment(attachment_id, attachment['fileName'])
                os.remove(attachment_path)

        except Exception as e:
            logging.warning(
                f'Skipping item named "{item["name"]}" because of this error: {repr(e)}'
            )
            continue

    logging.info('Saving changes to KeePass database.')
    kp.save()
    logging.info('Export completed.')
Example #16
0
    try:
        input_file = sys.argv[1]
        output_file = sys.argv[2]
        password = sys.argv[3]
    except:
        help()

try:
    open(input_file)
except:
    help()

try:
    open(output_file)
except:
    pky.create_database(output_file, password=password)

logins = csv.reader(open(input_file), delimiter=',')

kp = PyKeePass(output_file, password=password)

entries = parse_data(logins)

for entry in entries:
    kp.add_entry(kp.root_group,
                 get_name(entry[0]),
                 entry[1],
                 entry[2],
                 url=entry[0])

kp.save()
Example #17
0
class EntryFunctionTests(unittest.TestCase):

    # get some things ready before testing
    def setUp(self):
        self.kp = PyKeePass(os.path.join(base_dir, 'test.kdbx'),
                            password='******',
                            keyfile=os.path.join(base_dir, 'test.key'))

    #---------- Finding entries -----------

    def test_find_entries_by_title(self):
        results = self.kp.find_entries_by_title('root_entry')
        self.assertEqual(len(results), 1)
        results = self.kp.find_entries_by_title('Root_entry',
                                                regex=True,
                                                flags='i',
                                                first=True)
        self.assertEqual('root_entry', results.title)

    def test_find_entries_by_username(self):
        results = self.kp.find_entries_by_username('foobar_user')
        self.assertEqual(len(results), 2)
        results = self.kp.find_entries_by_username('Foobar_user',
                                                   regex=True,
                                                   flags='i',
                                                   first=True)
        self.assertEqual('foobar_user', results.username)

    def test_find_entries_by_password(self):
        results = self.kp.find_entries_by_password('passw0rd')
        self.assertEqual(len(results), 2)
        results = self.kp.find_entries_by_password('Passw0rd',
                                                   regex=True,
                                                   flags='i',
                                                   first=True)
        self.assertEqual('passw0rd', results.password)

    def test_find_entries_by_url(self):
        results = self.kp.find_entries_by_url('http://example.com')
        self.assertEqual(len(results), 2)
        results = self.kp.find_entries_by_url('http://example.com', first=True)
        self.assertEqual('http://example.com', results.url)

    def test_find_entries_by_notes(self):
        results = self.kp.find_entries_by_notes('entry notes')
        self.assertEqual(len(results), 1)
        results = self.kp.find_entries_by_notes('entry notes', regex=True)
        self.assertEqual(len(results), 2)
        results = self.kp.find_entries_by_notes('Entry notes',
                                                regex=True,
                                                flags='i',
                                                first=True)
        self.assertEqual('root entry notes', results.notes)

    def test_find_entries_by_path(self):
        results = self.kp.find_entries_by_path('foobar_group/group_entry')
        self.assertEqual(len(results), 1)
        results = self.kp.find_entries_by_path('foobar_group/Group_entry',
                                               regex=True,
                                               flags='i',
                                               first=True)
        self.assertIsInstance(results, Entry)
        self.assertEqual('group_entry', results.title)

    def test_find_entries_by_uuid(self):
        results = self.kp.find_entries_by_uuid('zF9+zSoASMqWIcIio0ewuw==')[0]
        self.assertIsInstance(results, Entry)
        self.assertEqual('zF9+zSoASMqWIcIio0ewuw==', results.uuid)
        self.assertEqual('foobar_user', results.username)

    def test_find_entries_by_string(self):
        results = self.kp.find_entries_by_string(
            {'custom_field': 'custom field value'})[0]
        self.assertIsInstance(results, Entry)
        self.assertEqual('custom field value',
                         results.get_custom_property('custom_field'))
        self.assertEqual('HnN4bHSVjEybPf8nOq1bVA==', results.uuid)

    def test_find_entries(self):
        results = self.kp.find_entries(title='Root_entry', regex=True)
        self.assertEqual(len(results), 0)
        results = self.kp.find_entries(title='Root_entry',
                                       regex=True,
                                       flags='i',
                                       first=True)
        self.assertEqual('root_entry', results.title)
        results = self.kp.find_entries(url="http://example.com")
        self.assertEqual(len(results), 2)
        results = self.kp.find_entries(notes="entry notes",
                                       url="http://example.com")
        self.assertEqual(len(results), 1)
        self.assertTrue(
            self.kp.find_entries(title='group_entry', first=True) in results)

        # test `group` argument
        results = self.kp.find_entries(title='foobar_entry', group=None)
        self.assertEqual(len(results), 3)
        group = self.kp.find_groups(name='foobar_group', first=True)
        results = self.kp.find_entries(title='foobar_entry', group=group)
        self.assertEqual(len(results), 2)

    #---------- Adding/Deleting entries -----------

    def test_add_delete_move_entry(self):
        unique_str = 'test_add_entry_'
        expiry_time = datetime.now()
        entry = self.kp.add_entry(self.kp.root_group,
                                  unique_str + 'title',
                                  unique_str + 'user',
                                  unique_str + 'pass',
                                  url=unique_str + 'url',
                                  notes=unique_str + 'notes',
                                  tags=unique_str + 'tags',
                                  expiry_time=expiry_time,
                                  icon=icons.KEY)
        results = self.kp.find_entries_by_title(unique_str + 'title')
        self.assertEqual(len(results), 1)
        results = self.kp.find_entries_by_title(unique_str + 'title',
                                                first=True)

        self.assertEqual(results.title, unique_str + 'title')
        self.assertEqual(results.username, unique_str + 'user')
        self.assertEqual(results.password, unique_str + 'pass')
        self.assertEqual(results.url, unique_str + 'url')
        self.assertEqual(results.notes, unique_str + 'notes')
        self.assertEqual(results.tags, [unique_str + 'tags'])
        # convert naive datetime to utc
        expiry_time_utc = expiry_time.replace(tzinfo=tz.gettz()).astimezone(
            tz.gettz('UTC'))
        self.assertEqual(results.icon, icons.KEY)

        sub_group = self.kp.add_group(self.kp.root_group, 'sub_group')
        self.kp.move_entry(entry, sub_group)
        results = self.kp.find_entries(path='sub_group/' +
                                       'test_add_entry_title',
                                       first=True)
        self.assertEqual(results.title, entry.title)

        self.kp.delete_entry(entry)
        results = self.kp.find_entries_by_title(unique_str + 'title',
                                                first=True)
        self.assertIsNone(results)

        # test adding entry which exists in another group
        subgroup = self.kp.find_groups(name='subgroup2', first=True)
        self.kp.add_entry(subgroup,
                          title='foobar_entry',
                          username='******',
                          password='******')

        # test adding entry to root which exists in subgroup
        self.kp.add_entry(subgroup,
                          title='foobar_entry2',
                          username='******',
                          password='******')
        self.kp.add_entry(self.kp.root_group,
                          title='foobar_entry2',
                          username='******',
                          password='******')

    #---------- Entries name collision exception -----------

    def test_raise_exception_entry(self):
        unique_str = 'test_add_entry_'
        entry = self.kp.add_entry(self.kp.root_group,
                                  unique_str + 'title',
                                  unique_str + 'user',
                                  unique_str + 'pass',
                                  url=unique_str + 'url',
                                  notes=unique_str + 'notes',
                                  tags=unique_str + 'tags',
                                  icon=icons.KEY)
        self.assertRaises(Exception, entry)

    # ---------- Entries representation -----------

    def test_print_entries(self):
        self.assertIsInstance(self.kp.entries.__repr__(), str)
Example #18
0
def write_token_data(entry_name,
                     kps_group,
                     token_data,
                     kps_pswd,
                     history_group=None):
    try:
        kp = PyKeePass(kps_file, password=kps_pswd)
        entry = kp.find_entries(title=entry_name, first=True)

        if entry is not None:
            notes = entry._get_string_field('Notes')
            updated_notes = ''
            current_envs = dict()

            for env in notes.split('\n'):
                try:
                    splitted = env.split(':')
                    current_envs.update({splitted[0]: splitted[1]})
                except:
                    pass

            for updated_environment in token_data.keys():
                if history_group:
                    if updated_environment == history_group:
                        entry.notes = updated_notes
                        entry.expiry_time = datetime.now() + timedelta(
                            days=365)
                        entry.expires = True

                else:
                    entry.notes = updated_notes
                    entry.expiry_time = datetime.now() + timedelta(days=365)
                    entry.expires = True

            for current_env_name, current_env_token in current_envs.items():
                if current_env_name not in token_data.keys():
                    token_data.update({current_env_name: current_env_token})

            for env_name, env_token in token_data.items():
                updated_notes += env_name + ': ' + env_token + '\n'

        else:
            group = kp.find_groups(name=kps_group, first=True)
            entry = kp.add_entry(group, entry_name, '', '')
            notes = ''

            for env_name, env_token in token_data.items():
                notes += env_name + ': ' + env_token + '\n'

            entry.notes = notes
            entry.expiry_time = datetime.now() + timedelta(days=365)
            entry.expires = True

        kp.save()

        return True

    except Exception as e:
        print('[ERRO] - Erro ao gravar dados no Keepass %s:\n%s' %
              (kps_file, str(e)),
              file=sys.stderr)
        pass