Open Querulous opened 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...)
@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?
@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.
@joaoportela As I remember merging databases doesn't leave them in identical state. Ideally synchronization should work as you described it.
@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).
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.
Is this issue still on your radar? How likely is this to be implemented?
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.
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.
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):