Dedicated .password-store w/minimal-attack-surface Secrets Collaboration #18

Open
opened 2023-08-13 22:09:06 +02:00 by so-rose · 0 comments

pass is a very simple bash script, which encrypts each secret in its own file with GPG (which is hardware-backed) in some .password-store git repository. This approach has bare-minimal attack surface, while being incredibly solid and featureful by virtue of gpgs and gits features - quite ideal for developers.

It is a very good idea to implement a dedicated .password-store directory to make it easier to separate python-support work from personal / other work, and to enable team collaboration.

In practice, this means:

  • Make sure there's easy-to-use GPG usage documentation available. It's not the simplest software.
  • Initialize a dedicated .password-store for this repo, of course subject to .gitignore as far as this repo is concerned.
  • Run a private passwords repository in the python-support organization, which all team members have access to. Note, though all team members can see the .gpg files, they can only open the ones they've been granted access to.

Then, add the following to .password-store (adapted from https://zwyx.dev/blog/shared-password-stores), do:

  • Place a .public-keys folder in the .password-store root, which contains a list of .asc files that bind GPG users (ex. John Doe <johndoe@example.com>) to GPG key fingerprints.
  • Place a .gpg-id file in the root of .password-store, with each line containing one GPG user (ex. John Doe <johndoe@example.com>) who may read all files in this and all subfolders of .password-store.
  • To control read access, place a similar .gpg-id file in the root of any folder that has different access.
  • To control write access, use Gitea's usual software dev tools: Protect main, and do thorough PR approval whenever someone changes a secret.
  • Enforce git commit signatures (this is essential), and consider implementing some scripts to check those signatures against .public-keys.
    • The team would also ideally manually check each other's GPG IDs in person, and even better, intersign keys == do a web of trust.
  • To tie it all together and actually encrypt .gpg secrets correctly according to .gpg-id files, just re-run pass init. It automatically reads .gpg-ids, checks against who the files are currently encrypted for, and re-encrypts if they don't match.
  • Ansible would now only need to include this new .password-store as the source of its lookup()s.
  • run.sh would also need to take care of git cloneing the passwords repo if needed, as part of its operation. As a result, any team member would be able to run any playbook, with secrets, so long as they've been given access to those secrets.
    • Part of this would also be preparing a concrete set of steps, ex. as a script or wiki page, for adding and removing (no-downtime requires secrets rotation, see #9) team members. Not that it's too complex, it's just nice to have it ready if/when such a thing happens.
`pass` is a very simple bash script, which encrypts each secret in its own file with GPG (which is hardware-backed) in some `.password-store` `git` repository. This approach has bare-minimal attack surface, while being incredibly solid and featureful by virtue of `gpg`s and `git`s features - quite ideal for developers. - `pass` Website: <https://www.passwordstore.org/> - `pass` Manpage: <https://git.zx2c4.com/password-store/about/> It is a very good idea to implement a dedicated `.password-store` directory to make it easier to separate `python-support` work from personal / other work, and to enable team collaboration. In practice, this means: - [ ] Make sure there's easy-to-use GPG usage documentation available. It's not the simplest software. - [x] Initialize a dedicated `.password-store` for this repo, of course subject to `.gitignore` as far as this repo is concerned. - [x] Run a private `passwords` repository in the `python-support` organization, which all team members have access to. *Note, though all team members can see the `.gpg` files, they can only open the ones they've been granted access to.* Then, add the following to `.password-store` (adapted from <https://zwyx.dev/blog/shared-password-stores>), do: - [x] Place a `.public-keys` folder in the `.password-store` root, which contains a list of `.asc` files that bind GPG users (ex. `John Doe <johndoe@example.com>`) to GPG key fingerprints. - [x] Place a `.gpg-id` file in the root of `.password-store`, with each line containing one GPG user (ex. `John Doe <johndoe@example.com>`) who may read all files in this and all subfolders of `.password-store`. - [x] To control read access, place a similar `.gpg-id` file in the root of any folder that has different access. - [ ] To control write access, use Gitea's usual software dev tools: Protect `main`, and do thorough PR approval whenever someone changes a secret. - [ ] Enforce `git` commit signatures (**this is essential**), and consider implementing some scripts to check those signatures against `.public-keys`. - *The team would also ideally manually check each other's GPG IDs in person, and even better, intersign keys == do a web of trust.* - [ ] To tie it all together and actually encrypt `.gpg` secrets correctly according to `.gpg-id` files, just re-run `pass init`. It automatically reads `.gpg-id`s, checks against who the files are currently encrypted for, and re-encrypts if they don't match. - A script, ex. <https://gist.github.com/Zwyx/aecea360db2c50a058a9b1f0c5287b45>, should probably be used in order to be explicit and chatty about what exactly is being re-encrypted. - This also provides a precise, auditable trail of *who had access to what, when*. Good for enterprises! - [x] Ansible would now only need to include this new `.password-store` as the source of its `lookup()`s. - [ ] `run.sh` would also need to take care of `git clone`ing the passwords repo if needed, as part of its operation. As a result, any team member would be able to run any playbook, with secrets, so long as they've been given access to those secrets. - Part of this would also be preparing a concrete set of steps, ex. as a script or wiki page, for adding and removing (no-downtime requires secrets rotation, see #9) team members. Not that it's too complex, it's just nice to have it ready if/when such a thing happens.
so-rose added the
enhancement
security
deployment-usability
labels 2023-08-13 22:09:31 +02:00
so-rose added this to the Refactor and Cleanup project 2023-08-13 22:09:41 +02:00
so-rose pinned this 2023-08-13 22:09:50 +02:00
so-rose self-assigned this 2023-08-17 12:45:34 +02:00
so-rose started working 2023-08-17 12:45:36 +02:00
so-rose stopped working 2023-08-17 12:46:08 +02:00
31 seconds
so-rose added this to the v0.2.0 milestone 2023-08-17 13:08:24 +02:00
so-rose removed their assignment 2023-11-28 10:20:01 +01:00
Sign in to join this conversation.
No Milestone
No Assignees
1 Participants
Notifications
Total Time Spent: 31 seconds
so-rose
31 seconds
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: python-support/python-support-infra#18
There is no content yet.