bridges: better credentials management

Labels: area/bridge kind/feature lifecycle/frozen priority/important-longterm triage/needs-information

Timeline

Michael Muré (MichaelMure) opened

Excerpt of the discussion:

Nice find, I had no idea it existed. Using real secret store instead of the git config is definitely a nice thing to have.

Toying a bit with that thing, I found that:

  1. it's a way to interact with user-specified secret storage
  2. if no credential helper is configured (virtually 100% of users) it default to a one off prompt. Nothing is stored, even between git invocation.
  3. a cache system exist (need to be configured) to store credential in memory in between git invocation
  4. a storage system exist (need to be configured) to store credential in a clear-text file
  5. the expressiveness of this credential system is highly coupled with what git know: URLs, login, password. Storing tokens or metadata is kinda hacky.

So, what I derive from that is:

  • this system is deeply tied to what git understand but could be abused for our needs. A standardized way to talk to a secret store is neat, especially as it could require no git-bug specific configuration.
  • instead of being a new kind of credential (token, password, login/password), this would really be a new way to store credentials for the credential system
  • credential's metadata can keep being stored in the git config. Shoehorning those into the git credential system seems a bit too much
  • in term of UX, an explicit choice between the git config and this more secure system is not required each time a credential is stored. It seems ok to me to use that better system if available and default to the git config if not. It may cause problems though if this system become unavailable and credentials are left in an incoherent state.

Does that sounds reasonable to you ? If so I'll merge my branch and we can add this feature later as it's orthogonal to everything else. Only the storage functions will be impacted.

Originally posted by @MichaelMure in https://github.com/MichaelMure/git-bug/pull/324#issuecomment-586239255

Michael Muré (MichaelMure) added label enhancement

Michael Muré (MichaelMure) added label area/bridge

Julian Berman (Julian) commented

Not sure if here's the right place to add this comment, but even beyond git-credential, isn't using the git config a bit surprising? It surprised me certainly -- I have my configuration itself tracked in git, and seeing secret credentials pop up in the file breaks being able to do that (of course I noticed, but yeah I definitely didn't expect secrets to be added to the global git config as part of setting up git-bug with a bridge)

karlicoss (karlicoss) commented

Agree that adding directly to git config is a bit extreme (because people usually expect this file to be public). Perhaps an easy fix without changing the model would be using an include section in git config instead:

[include]
    path = .config/git-bug/token

and git-bug keeps its token sections .config/git-bug/token.

Michael Muré (MichaelMure) commented

Using the git config is not perfect but it has a very nice property: it works cross platform and across repository very easily. I'm open to suggestion and help to change that though.

Julian Berman (Julian) commented

Cool! Glad to hear. In Python-land if it were me I may be considering something like the keyring module.

Maybe there's something similar for go (OS-agnostic access to the operating system's credentials keychain)

But can have a think or look around.

sudoforge commented (edited)

Just a note: using the include section won't work, because git-bug currently uses the --global and --local flags respectively, which do not follow includes. If specifying a file is desired, includes can be followed by also using --include.

Since this is off-topic for this issue, it's probably best to continue the discussion in #406.

Michael Muré (MichaelMure) closed the bug

Moritz Poldrack (mpldr) commented

Storing the Secrets in a freedesktop.org Secret Service would probably be the best way to solve this on Linux.

sudoforge commented

my vote would be for a systemd-creds entry for linux. unless that keyring lib already supports that.

Moritz Poldrack (mpldr) commented

Would that even be applicable for git-bug? If memory serves me well systemd-creds is intended to be used for credentials used by units.

sudoforge commented

it's a generic tool for encrypting and decrypting things. yes, it's built into systemd and available to units, but there's nothing stopping anyone from using systemd-creds directly.

Moritz Poldrack (mpldr) commented

Then I would suggest to instead opt for the system-independent standard already implemented by various password (and other secrets) managers.

sudoforge commented

If we're looking for a cross-platform solution, letting the user pick how their credentials are stored and using git-credential is actually what I'd argue for, since that is a) available in Git, requiring no additional user-managed dependency, and b) not limiting the user to supported secret backends (e.g. a particular keyring).

I do not have gnome-keyring installed, and have no desire to install it just so I can use it for managing my git-bug credentials -- I'd much prefer to use my existing password store.

Moritz Poldrack (mpldr) commented

On Thu Mar 2, 2023 at 5:38 PM CET, sudoforge wrote:

If we're looking for a cross-platform solution, letting the user pick how their credentials are stored and using git-credential is actually what I'd argue for, since that is a) available in Git, requiring no additional user-managed dependency, and b) not limiting the user to supported secret backends (e.g. a particular keyring).

I agree that a cross-platform version should be provided, but I also think it's important to have a secure way to access credentials that (worst case) could allow a full account takeover.

I do not have gnome-keyring installed, and have no desire to install it just so I can use it for managing my git-bug credentials -- I'd much prefer to use my existing password store.

There's no way in hell, I'd install that either :D That's not the only password manager that supports this API though. KeePassXC, Bitwarden, gnome-keyring, and various other password managers are using it and every single on of them is a more appropriate storage for credentials than a textfile in your ~.

-- Moritz Poldrack https://moritz.sh

sudoforge commented

That's not the only password manager that supports this API though

The spirit of my comment was that requiring installing some-specific-password-manager that may not be the one I use for everything else is not something I'd support. Phrased differently, I think the solution implemented should be one-size-fits-all, without any particular requirement for the end user to install a specific password manager that implements that API.

To that end, git-credentials is a good candidate, as it can proxy out to an external command, e.g. gopass, op (1Password's CLI), or a script the user writes that performs whatever necessary logic to fetch their password.

Michael Muré (MichaelMure) commented

The problem with git-credentials is that git-bug is using go-git, not git installed on the system. Go-git does not support git-credentials as far as I know, so we are back to whatever golang package exist to deal with credentials.

sudoforge commented (edited)

Maybe I'm misunderstanding something, but why wouldn't we be able to call out to whatever is configured with credential.helper?

$ cat /some/git/config
[credential "foo"]
    helper = "/usr/bin/password-manager --flag1 --flag2 blahblahblah"

I suppose this has the downside of supporting arbtirary executables, but fetching this information is available via go-git , and executing it (grabbing the output) is available via os/exec and friends.

Assuming the configured helper is secure, this leaves git-bug with the same responsibility it would have if using some other backend; that is, ensuring that the received contents are secure and ideally zeroed-out or otherwise removed from memory after usage (memguard?).

Michael Muré (MichaelMure) commented

I see. Put that way it's not entirely unreasonable as it allows users to setup their own thing. Launching an arbitrary executable is a very large can of worm though (and one of the reason I moved to use go-git). I don't know how to make that properly secure.

On the other hand, the majority of users (by a large margin) won't have a credential helper configured. What then?

sudoforge commented (edited)

Yeah, the proper sandboxing of a user-provided executable is something that escapes me, and is likely not something to try to tackle ourselves; I think reviewing what other tools do and relying on the recommendations of the larger Go community would be a good way to gather knowledge and tips on doing this, if desired.

On the other hand, the majority of users (by a large margin) won't have a credential helper configured. What then?

I think this is the same problem we have if we dictate that a user must install some-password-manager that a) implements Secret Service or b) is a desired backend for git-bug to use. The only viable solution I can think of (sans enforcing users to install the tool or configure git-credential) is to have git-bug default to some internal method of storing credentials, e.g. implementing Secret Service on its own... which then begets the question, why support other methods in the first place?

Michael Muré (MichaelMure) commented

is to have git-bug default to some internal method of storing credentials, e.g. implementing Secret Service on its own

That became meta real quick ;-). The idea is to delegate that to something that does it better. Let's not implement it ourselves, we would just do it terribly.

From a UX point of view, I'm not considering to ask users to install a dependency (be it gnome-keyring, systemd ...).

On the other hand, if there is a better option available to store credentials than a random file on disk, why not? But then, we quickly end in that situation: https://github.com/99designs/keyring/issues/74

I suppose a better path would be to implement such cascading (and migrating?) support for multiple credential stores, with something like this priority order (from lower to higher prio):

  • encrypted file in user's home (as currently)
  • systemd (if go-keyring ever add support for it)
  • freedesktop's SecretService (would cover a lot of user)
  • git credentials (if we have a really secure way to do it)

sudoforge commented (edited)

That became meta real quick ;-). The idea is to delegate that to something that does it better. Let's not implement it ourselves, we would just do it terribly.

Of course; DIYing this would be a non-optimal solution.

A simpler implementation of "cascading support" is simply:

  • an encrypted file in the user's home directory (the current solution)
  • git credentials

because git-credentials can be configured (by the user) to proxy out to whatever other solution they want.

Michael Muré (MichaelMure) opened the bug

Michael Muré (MichaelMure) changed the title from bridges: better credentials management to bridges: better credentials management

Steve Moyer (smoyer64) commented

The chezmoi application supports a variety of tools that store user secrets and lets the user decide which one to use. This obviously has costs from a development perspective but eliminates the vi versus emacs style argument over what secret storage is best. Perhaps we start with an abstraction that would (eventually) support more than one option?

On Sun, Mar 5, 2023 at 4:49 AM Michael Muré @.***> wrote:

Reopened #327 https://github.com/MichaelMure/git-bug/issues/327.

— Reply to this email directly, view it on GitHub https://github.com/MichaelMure/git-bug/issues/327#event-8667640844, or unsubscribe https://github.com/notifications/unsubscribe-auth/AACQFDLQQP7END2IL4JB5UTW2ROT5ANCNFSM4KVYS3CQ . You are receiving this because you are subscribed to this thread.Message ID: @.***>

-- Sent from my iBerry MacPhone

sudoforge commented

I don't see how using another application to abstract the storage mechanism away is any different from using some command specified in gitconfig (which is what git-credentials does with the credential.helper parameter), which, as I've detailed in other comments in this thread, avoids requiring the user to install a new dependency, and avoids any sort of limitation on how the user wants to provide credentials to git-bug.

In fact, I think referencing git-credential here has added confusion around what we need to do. Let's scratch that topic.

Piping out to a user-defined command to fetch credentials, securely storing that input somewhere, and going about our business seems to be the most straightforward way to accomplish this without much complexity.

➜ git config --get-regex 'git-bug.*'
git-bug.credential_command /path/to/some/tool --foo --bar baz

We then get the value for this, perform whatever validation we need to (e.g. does the program exist in PATH?), execute it, report back and short circuit if it fails, else take the stdout as input, store it securely (memguard?), and use it as the credential when authenticating.

Steve Moyer (smoyer64) commented

I didn't mean we should use chezmoi ... I meant we should pick an abstraction that ultimately allows the user to choose. I'm actually in agreement with you WRT using something like the credential.helper.

github-actions (github-actions) commented

This bot triages untriaged issues and PRs according to the following rules:

  • After 90 days of inactivity, the lifecycle/stale label is applied
  • After 30 days of inactivity since lifecycle/stale was applied, the issue is closed

To remove the stale status, you can:

  • Remove the lifecycle/stale label
  • Comment on this issue

github-actions (github-actions) added label lifecycle/stale

sudoforge removed label lifecycle/stale

sudoforge added label lifecycle/frozen

sudoforge added label priority/important-longterm

sudoforge removed label enhancement

sudoforge added label kind/feature

sudoforge added label triage/needs-information

sudoforge removed label lifecycle/pinned