Import KeePass secrets in Hashicorp Vault

Warning

the version 2.0.0 introduced breaking changes, make sure to read the release notes

vault-keepass-import is a CLI to import KeePass secrets (using pykeepass) in Hashicorp Vault (using hvac-cli).

Bugs and feature requests can be found in the issue tracker

The Title of the entry is used as the last component of the secret path. For instance if importing an entry with Title mysecret in the mygroup group, the path secret/keepass/mygroup/mysecret will be used.

There may be multiple entries with the same title in a group. The path is made unique by appending the UUID of the entry to the title. For instance two entries with the same title1 in the group group1 will be imported as group1/title1 (TJxu0nxlyEuaKYNYpi0NPQ==) and group1/title1 (kFl/iRsoVUWDUdmmCDXwJg==). The UUID is not appended if the title is unique.

If the –rewrite-key option is specified it will workaround Vault web UI and CLI bugs by rewriting the key of each entries as follow:

  • All trailing whitespaces are trimmed, in each path component (i.e. s|s+/|/|g and s|s+$||). This is required because of a bug in Vault 1.0.2, 1.0.3 that makes it impossible to list a path that ends with a whitespace via the CLI (the web UI works fine).

  • All unsafe characters (#,%,*,+,(,[,\, the ascii range [x00-x1fx7f]) are replaced with an underscore. The characters #,%,*,+,(,[,\ are considered unsafe because of a bug in Vault 1.0.2, 1.0.3.

  • User name from the Entry tab is imported as is under the key username

  • Password from the Entry tab is imported as is under the key password

  • URL from the Entry tab is imported as is under the key url

  • Notes from the Entry tab is imported as is under the key notes

  • Expires from the Entry tab is imported under the key expiry_time. It is only imported if set and converted to epoch.

  • Tags from the Properties tab is imported as is under the key tags

  • UUID from the Properties tab is imported as is under the key uuid

  • String fields from the Advanced tab are imported as is with a key matching their Name and a value set to their Value

  • File attachments from the Advanced tab are imported with a key set to id/filename (for instance if there only is one foo.txt attachment, it will have the key 0/foo.txt) and the value is base64 encoded. For instance, the actual value can be retrieved from the command line with:

    $ vault kv get -field 8/attached.txt secret/mysecret | base64 --decode
    
  • mtime, ctime, atime are always imported and converted to epoch

Quick start

$ pip3 install vault-keepass-import
$ export VAULT_ADDR=https://myvault.com:8200
$ export VAULT_TOKEN=mytoken
$ vault-keepass-import database.kdbx
KeePass password:
$ vault kv list secret/keepass
Keys
----
Group1/
Group2/
secret1
secret2
$ vault kv get secret/keepass/secret1
====== Metadata ======
Key              Value
---              -----
created_time     2019-01-29T13:52:32.79894513Z
deletion_time    n/a
destroyed        false
version          1
==== Data ====
Key      Value
---      -----
atime    1465498383
ctime    1465498332
icon     0
mtime       1527099465
password    strongpassword
username    someuser
uuid        5uCDWvHUQjyGnyBlRw9CFA==

Testing the import

  • Download and install Hashicorp Vault

  • Run vault in development mode (the storage is reset when it restarts)

    $ vault server -dev -dev-root-token-id=mytoken
    
  • Assuming the password to the KeePass database is kdbxpassword, run an import with:

    $ vault-keepass-import --token mytoken \
                           --password kdbxpassword \
                           database.kdbx
    

Command help

usage: vault-keepass-import [-h] [--dry-run] [--token TOKEN]
                            [--address ADDRESS] [--tls-skip-verify]
                            [--ca-cert CA_CERT] [--client-cert CLIENT_CERT]
                            [--client-key CLIENT_KEY] [--rewrite-key]
                            [--mount-point MOUNT_POINT] [--kv-version {1,2}]
                            [--version] [--verbose] [-p PASSWORD] [-f KEYFILE]
                            [--prefix PREFIX] [-e] [-l]
                            KDBX

Positional Arguments

KDBX Path to the KeePass database

Named Arguments

--dry-run

Show what would be done but do nothing

Default: False

--token Vault token. It will be prompted interactively if unset. This can also be specified via the VAULT_TOKEN environment variable.
--address

Address of the Vault server. This can also be specified via the VAULT_ADDR environment variable.

Default: “http://127.0.0.1:8200

--tls-skip-verify
 

Disable verification of TLS certificates. Using this option is highly discouraged and decreases the security of data transmissions to and from the Vault server. The default is false. This can also be specified via the VAULT_SKIP_VERIFY environment variable.

Default: False

--ca-cert Path on the local disk to a single PEM-encoded CA certificate to verify the Vault server’s SSL certificate. This can also be specified via the VAULT_CACERT environment variable.
--client-cert Path on the local disk to a single PEM-encoded CA certificate to use for TLS authentication to the Vault server. If this flag is specified, –client-key is also required. This can also be specified via the VAULT_CLIENT_CERT environment variable.
--client-key Path on the local disk to a single PEM-encoded private key matching the client certificate from -client-cert. This can also be specified via the VAULT_CLIENT_KEY environment variable.
--rewrite-key

Rewrite the key to avoid UI problems and print a warning. Workaround https://github.com/hashicorp/vault/issues/6282; https://github.com/hashicorp/vault/issues/6213; replace control characters and percent with an underscore

Default: False

--mount-point

KV path mount point, as found in vault read /sys/mounts

Default: “secret”

--kv-version

Possible choices: 1, 2

Force the Vault KV backend version (1 or 2). Autodetect from vault read /sys/mounts if not set.

--version show program’s version number and exit
--verbose

Verbose mode

Default: False

-p, --password Password to unlock the KeePass database. Prompted interactively if not set.
-f, --keyfile Keyfile path to unlock the KeePass database
--prefix

Vault prefix (destination of the import)

Default: “keepass/”

-e, --erase

Erase the prefix (see –prefix) prior to the import operation

Default: False

-l, --lowercase
 

Force keys to be lowercased

Default: False