keepassxreboot / keepassxc

KeePassXC is a cross-platform community-driven port of the Windows application “Keepass Password Safe”.
https://keepassxc.org/
Other
20.82k stars 1.44k forks source link

Full synchronization on CLI #2184

Open Querulous opened 6 years ago

Querulous commented 6 years ago

It would be great if keepassxc-cli has option to synchronize databases and leave them in identical state.

Expected Behavior

One command to synchronize two databases for example:

keepassxc-cli synchronize $first $second

Current Behavior

Currently I have to run two commands to achive this (and type password twice):

keepassxc-cli merge $first $second
keepassxc-cli merge $second $first
liar666 commented 6 years ago

The problem with sync is when there are conflicts... To manage all the kinds of conflicts that can occur you would have to recreate a complete git-like tool :{

If your problem is just about typing twice the password and you're using bash, a workaround could be: user$ KEEPASS_PASS=MyPass user$ keepassxc-cli merge $first $second<<EOF ${KEEPASS_PASS} EOF user$ keepassxc-cli merge $second $first<<END ${KEEPASS_PASS} END user$ unset KEEPASS_PASS

As an exercise, I let it up to you to rewrite that as a script that does not store the pass in clear (e.g. expecting the env var to be set or asking it on the command line but with no echo...)

joaoportela commented 5 years ago

@liar666

The problem with sync is when there are conflicts... To manage all the kinds of conflicts that can occur you would have to recreate a complete git-like tool :{

keepass2 has this feature, no conflict resolution dialog needed. I believe that's because, for the worst case scenario, your intended latest version ends up in the history tab. Wouldn't the same problem apply to the merge command?

joaoportela commented 5 years ago

@Querulous Wouldn't these commands be equivalent to the desired synchronize feature?

keepassxc-cli merge $first $second
cp $first $second

That being said, I agree with you that having a "synchronize" command would make the user more confident that he is doing the right thing and ends up with both databases in the correct state.

Querulous commented 5 years ago

@joaoportela As I remember merging databases doesn't leave them in identical state. Ideally synchronization should work as you described it.

joaoportela commented 5 years ago

@Querulous I was just proposing that, based on the documentation.

   merge [options] <database1> <database2>
         Merges two databases together. The first database file is going to be  replaced  by
         the  result  of  the merge, for that reason it is advisable to keep a backup of the
         two database files before attempting a merge. In the case that both databases  make
         use of the same credentials, the --same-credentials or -s option can be used.

Since the <database1> has the result of the merge, you can just copy it over <database2> to end up with two complete databases (instead of doing two merges).

AlkaliX commented 4 years ago

Hi Team, Details of Sync feature from KeePass are described on the Keepass help page https://keepass.info/help/v2/sync.html#tech

The synchronization algorithm is rather complex and it would take many pages to describe in detail how it's working. Developers interested in this can have a look into the KeePass source code. Here are the most important properties of the synchronization algorithm:

In order to decide which copy of an object is the latest one, KeePass mainly uses the last modification time of the object (which KeePass updates automatically each time the object is changed). The synchronization is performed on entry level. This e.g. means that a combination of user name / password is always consistent (synchronization on field level will not be implemented, because combinations could become inconsistent with this). In case of parallel updates and collisions, KeePass tries to store all information in an appropriate place. For example, when you have an entry E in a database A, make a copy B of A, change E in B, change E in A, and synchronize A and B, then E in A is treated as current and the changes made to E in B are stored as a history version of E (see tab 'History' in the entry dialog), i.e. the changes made in B aren't lost.

joaoportela commented 2 years ago

Is this issue still on your radar? How likely is this to be implemented?

ringerc commented 1 year ago

Here's what I'm using for a sync to Google Drive, so I can merge changes made using keepass2android on Android with changes made using KeepassXC on my Linux desktop. Because I'm using rclone it should work just fine for lots of other cloud stores like DropBox, OneDrive, AWS S3, whatever.

This script may permanently and unrecoverably mangle your databases or entire computer. Do not run it without backups.

Make sure you exit any interactive KeepassXC sessions before running.

#!/bin/bash
KEEPASSDB_LOCAL=$HOME/pathtomydb.kdbx
KEEPASSDB_REMOTE=mygdriveaccount:pathtothedb.kdbx 

if ! grep -q '^RCLONE_ENCRYPT' $(rclone config file | tail -1); then
  echo 1>&2 "insecure unencrypted rclone config detected, use 'rclone config' to set config password"
  exit 2
fi

tmpdir=(mktemp -d -p '' keepass_sync_XXXXXXXX)
trap 'rm -r ${tmpdir}' EXIT

tmpdb="${tmpdir}/$(basename $KEEPASSDB_LOCAL)"

echo 1>&2 "downloading remote db"
rclone copyto "${KEEPASSDB_REMOTE}" "${tmpdb}"
if keepassxc-cli merge "${KEEPASSDB_LOCAL}" "${tmpdb}"
then
  echo 1>&2 "Uploading merged db"
  rclone copyto --interactive "${KEEPASSDB_LOCAL}" "${KEEPASSDB_REMOTE}"
else
  echo 1>&2 "unclean exit from merge, skipping upload"
fi

Be warned that there is a race condition here. Changes made to the remote file after the remote is downloaded will be lost. Don't do that. To make this free from races in the absence of a co-operative protocol with other apps accessing it would require a way to take some kind of exclusive write lease on the remote file.

To use this, you'll first have to install rclone then run rclone config and set up an account for your preferred remote store. Make sure to enable rclone config encryption as rclone's defaults are terribly insecure - https://rclone.org/docs/#configuration-encryption , https://github.com/rclone/rclone/issues/7314

Also beware, KeepassXC doesn't seem to keep the filehandle to the database file open while running, so I can't use fuser in the below script to detect if it's open and refuse to run if the DB is open locally. It doesn't appear to keep a lockfile for the db either; it has a generic /tmp/keepassxc-${USER}.lock file, but this is unhelpful for identifying whether a given DB is open or not. As a result, this script expects you to make sure keepassxc isn't still running.

droidmonkey commented 1 year ago

Make sure you exit any interactive KeepassXC sessions before running

Why? The gui will detect when the db file is updated and silently reload it.