Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Summary: switch from pwstore to password-store for (and only for) TPA passwords

Background

TPA has been using a password manager called pwstore for a long time now. It's time to evaluate how it has served us. An evaluation of all password needs is being performed in issue 29677 but this proposal discusses only standalone passwords managed by TPA.

That specifically excludes:

  • passwords managed by other teams or users
  • moving root or LUKS password out of the password manager (could be accomplished separately)

Current problems

In any case, during a recent offboarding process (tpo/tpa/team#41519), it became very clear that our current password manager (pwstore) has major flaws:

  1. key management: there's a separate keyring to manage renewals and replacement; it is often forgotten and duplicates the separate .users metadata that designates user groups

  2. password rotation: because multiple passwords are stored in the same file, it's hard or impossible to actually see the last rotation on a single password

  3. conflicts: because multiple passwords are stored in the same file, we frequently get conflicts when making changes, which is particularly painful if we need to distribute the "rotation" work

  4. abandonware: a pull request to fix Debian bookworm / Ruby 3.1 support has been ignored for more than a year at this point

  5. counter-intuitive interface: there's no command to extract a password, you're presumably supposed to use gpg -d to read the password files, yet you can't use other tools to directly manipulate the password files because the target encryption keys are specified in a meta file

  6. not packaged: pwstore is not in Debian, flatpak, or anything else

  7. limited OTP support: for sites that require 2FA, we need to hard-code a shell command with the seed to get anything working, like read -s s && oathtool --totp -b $s

Proposal

The proposal is to adopt a short-term solution to some of the problems by switching to passwordstore. It has the following advantages:

  • conflict isolation: each password is in a separate file (although they can be store all in one file), resolving conflict issues

  • rotation support extensions like pass-update make it easier to rotate passwords (ideally, sites would support the change-password-url endpoint and pass would too, but that standard has seen little adoption, as far as we know)

  • OTP support: pass-otp is an extension that manages OTP secrets automatically, as opposed to the command-line cut-and-paste approach we have now

  • audit support: pass-audit can review a password store and look for weak passphrases

Limitations

Pass is not without problem:

  • key management is also limited: key expiry, for example, would still be an issue, except that the keyid file is easier to manage, as its signature is managed automatically by pass init, provided that the PASSWORD_STORE_SIGNING_KEY variable is set

  • optional store verification: it's possible that operators forget to set the PASSWORD_STORE_SIGNING_KEY variable which will make pass accept unsigned changes to the gpg-id file which could lead a compromise on the Git server be leveraged to extract secrets

  • limited multi-store support: the PASSWORD_STORE_SIGNING_KEY is global and therefore makes it complicated to have multiple, independent key stores

  • global, uncontrolled trust store: pass relies on the global GnuPG key store although in theory it should be possible to rely on another keyring by passing different options to GnuPG

  • account names disclosure: by splitting secrets into different files, we disclose which accounts we have access to, but this is considered a reasonable tradeoff for the benefits it brings

Issues shared with pwstore

Those issues are not specific to pass, and also exist in pwstore:

  • mandatory client use: if another, incompatible, client (e.g. Emacs) is used to decrypt and re-encrypt the secrets, it might not use the right keys

  • GnuPG/OpenPGP: pass delegates cryptography to OpenPGP, and more specifically GnuPG, which is suffering from major usability and security issues

  • permanent history: using git leverages our existing infrastructure for file-sharing, but means that secrets are kept in history forever, which makes revocation harder

  • difficult revocation: a consequence of having client-side copies of passwords means that revoking passwords is more difficult as they need to be rotated at the source

Layout

This is what the pwstore repository currently looks like:

anarcat@angela:tor-passwords$ ls
000-README  entroy-key.pgp  external-services-git.pgp  external-services.pgp  hosts-extra-info.pgp  hosts.pgp  lists.pgp  ssl-contingency-keys.pgp  win7-keys.pgp

I propose we use the following layout in the new repository:

  • dns/ - registrars and DNS providers access keys: joker.com, netnod, etc
  • hosting/ - hosting providers: OSUOSL, Hetzner, etc
  • lists/ - mailing list passwords (eventually deprecated by Mailman 3)
  • luks/ - disk encryption passwords (eventually moved to Arver or Trocla)
  • misc/ - whatever doesn't fit anywhere else
  • root/ - root passwords (eventually moved to Trocla)
  • services/ - external services: GitHub, Gitlab.com, etc

The mapping would be as such:

pwstoreextrapass
entropy-keymisc/
external-services-git@gitadmservices/
external-servicesdns/ hosting/ services/
hosts-extra-infodns/ hosting/ luks/ services/
hostsroot/
lists@listlists/
ssl-contingency-keysmisc/
win7-keysmisc/

The groups are:

@admins  = anarcat, lavamind, weasel
@list    = arma, atagar, qbi, @admins
@gitadm  = ahf

Affected users

This only concerns passwords managed by TPA, no other users should be affected.

Alternatives considered

The following were previously discussed or considered while writing this proposal.

Bitwarden

Bitwarden is the obvious, "larger" alternative here. It was not selected for this project because we want a short-term solution. We are also not sure we want to host the more sensitive TPA passwords alongside everyone else's passwords.

While Bitwarden does have an "offline" mode, it seems safer to just keep things simple for now. But we do keep that service in mind for future, organisation-wide improvements.

Alternative pass implementations

Pass is a relatively simple shell script, with a fairly simple design: each file is encrypted with OpenPGP encryption, and a .gpg-id lists encryption keys, one per line, for files inside the (sub)directory.

Therefore, other implementations have naturally crept up to provide alternative implementations. Those are not detailed here because they are mostly an implementation detail: since they are compatible, they share the same advantages and limitations of pass, and we are not aware of any implementation with significant enough differences to warrant explicit analysis here. We'll just mention gopass and ripasso as alternative implementations.

OpenPGP alternatives

Keepass, or probably more KeepassXC is an obvious, local-first alternative as well. It has a number of limitations that make it less usable for us: everything is stored in a single file, with not built-in mechanism for file-sharing. It's strongly geared towards a GUI usage as well. It is more suitable to individual than teams.

Another alternative is Age encryption, which is a "simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability". It uses X25519 keys for encryption and is generally compatible only with other Age clients, but does support encryption to SSH keys (RSA and ED25519). Their authors have forked pass to provide a password manager with similar features, but lacking authentication (as age only provides encryption). Minisign might be somehow integrated in there but that that point, you're wondering what's so bad about OpenPGP that you're reinventing it from scratch. Gopass has an experimental age backend that could be used to transition to age, if we ever need to.

In theory, it's possible to use SSH keys to encrypt and decrypt files, but there are not, as far as we know (and apart from Age's special SSH mode), password managers based on SSH.

Alternative synchronisation mechanisms

The "permanent history" problem mentioned above could be solved by using some other synchronisation mechanism. Syncthing, in particular, could be used to synchronise those files securely, in a peer-to-peer manner.

We have concerns, however, about the reliability of the synchronisation mechanism: while Syncthing is pretty good at noticing changes and synchronising things on the fly, it can be quirky. Sometimes, it's not clear if files have finished syncing, or if we really have the latest copy. Operators would need to simultaneously be online for their stores to keep updating, or a relay server would need to be used, at which point we now have an extra failure point...

At that point, it might be simpler to host the password manager on a more "normal" file sharing platform like Nextcloud.

This issue is currently left aside for future considerations.

Approval

This has already been approved during a brief discussion between lavamind and anarcat. This document mostly aims at documenting the reasoning for posterity.

References