Reliable 1Password backup written in Python

By | November 23, 2022

I’ve done a pretty deep dive comparing the features of various password managers, but one feature I didn’t cover in that analysis was backup for business customers. What commitments does the vendor make in terms of backup/restore? Do they promise to be able to restore data that is accidentally or maliciously modified or deleted by a user? If not, do they provide the ability for the business to export regular, automated backups of their data?

Unfortunately, the answers to these questions for 1Password is not great. While they say they will always try to help with data recovery issues and are often able to recover incorrectly deleted or modified data, they don’t make any commitments to be able to do so. They also don’t provide any easy way for a business to securely export their data for backup.

To address this deficiency when I worked at Numerated Growth Technologies, I wrote this 1password-backup script, which Numerated has kindly agreed to open-source. The script uses the 1Password CLI to iterate through the caller’s Private vault and all shared vaults to which they have access, download all of their contents, and then pack them up into a compressed tar file which can optionally be encrypted with gpg. Backing up the Private vault can be disabled if the caller only wants shared vaults to be in the backup. This script therefore enables any Owner or Administrator of a 1Password account to easily back it up.

The script should also work perfectly well for individual 1Password users or 1Password family users who want to back up their accounts.

To be clear, there are a couple of important things this script does not do:

  1. The script won’t back up other users’ Private vaults in a business or family 1Password account. As far as I know there’s no way to do this without logging in separately as each individual user, and this is arguably the correct behavior.
  2. This is just an export script, not an import script. If you ever need to recover from a major 1Password disaster and get a whole bunch of data back into 1Password, you’re going to have to write a new script to read the backup and import its contents. We never did that at Numerated because we never had to. 😉 I’m sure a PR to the repository would be gratefully accepted!
    On the other hand, obviously if you just need to pull a small amount of data out of a backup, you can browse through the archive to do that and then manually enter the data back into 1Password if desired.

On the subject of gpg encryption, when we started using this script to regularly back up our shared 1Password vaults at Numerated, we also wanted to make sure that we didn’t broaden our attack surface by putting backups somewhere on the network where an attacker could find them and make use of all the credentials stored in them. That’s easy enough, but we also wanted to protect against insider threats, e.g., we didn’t want a disgruntled or departing employee who was previously responsible for backups to be able to grab an old backup, take it with them, and use its contents. To satisfy these requirements, we gave the private gpg key from the keypair used by the backups a long, random passphrase, used Shamir’s Secret Sharing Scheme (ssss) to split the passphrase into five shares with two shares required to reconstruct it, and distributed those shares to five different employees. We told these employees that contrary to our normal instruction that company-related secrets should only be stored in 1Password, this particular secret should actually be stored in their personal password manager or some other private, secure location, because (a) it won’t do any good for it to be in 1Password if the reason we need it is to restore 1Password, and (b) we don’t want any of the shares to be accessible to anyone other than the person it was distributed to, but it would be accessible to our 1Password administrators if it were stored in 1Password.

Print Friendly, PDF & Email
Share

Leave a Reply

Your email address will not be published. Required fields are marked *