Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full synchronization on CLI #2184

Open
Querulous opened this issue Aug 6, 2018 · 9 comments
Open

Full synchronization on CLI #2184

Querulous opened this issue Aug 6, 2018 · 9 comments

Comments

@Querulous
Copy link

Querulous commented Aug 6, 2018

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
Copy link

liar666 commented Aug 22, 2018

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
Copy link

@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
Copy link

@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
Copy link
Author

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

@joaoportela
Copy link

joaoportela commented Oct 9, 2018

@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
Copy link

AlkaliX commented Dec 4, 2019

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
Copy link

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

@ringerc
Copy link

ringerc commented Sep 17, 2023

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 , rclone/rclone#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
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants