canonical / docker-snap

https://snapcraft.io/docker
MIT License
52 stars 27 forks source link

Provide docker-credential-helpers interface #10

Open andrewsomething opened 3 years ago

andrewsomething commented 3 years ago

The basic use case would be to allow users of the docker snap to to use docker-credential-secretservice to store their credentials via a workflow like:

$ snap install docker
$ snap install docker-credential-secretservice
$ snap connect docker:credentials-helpers docker-credentials-secretservice:credentials-helpers

Additionally, it would be nice to allow other snaps to be able to call docker-credential-secretservice. For example, the doctl snap has a command that can be used to log in Docker to the DigitalOcean container registry. We have a personal-files plug that grants access to ~/.docker/config.json. This works as expected when the credentials are stored in the file, but fails when a credential helper is configured. See: https://github.com/digitalocean/doctl/issues/876

Additional discussion: https://forum.snapcraft.io/t/docker-snap-docker-credential-secretservice-credentials-helper/14198

tianon commented 3 years ago

I'm definitely on board with this in concept, but don't have the bandwidth/interest to maintain a docker-credential-secretservice snap as well. I'm happy to review/implement any changes needed in the docker snap to help facilitate this with a little guidance on how it's supposed to work!

I guess we need to add something like the following?

plugs:
  credentials-helpers:
    interface: content
    content: credentials-helpers
    target: $SNAP/credentials-helpers

I'm honestly not actually sure what that means -- is that for other snaps to be able to share that directory and provide additional content for the docker snap to use, such as binaries? When they get invoked, do they then get invoked in the Docker snap's confinement? (To put that another way, what are the implications for a user to determine whether they trust XYZ Snap to provide arbitrary content to Docker and thus connect this interface?)

anonymouse64 commented 3 years ago

is that for other snaps to be able to share that directory and provide additional content for the docker snap to use, such as binaries?

yes

When they get invoked, do they then get invoked in the Docker snap's confinement? (To put that another way, what are the implications for a user to determine whether they trust XYZ Snap to provide arbitrary content to Docker and thus connect this interface?)

yes but I wonder if it's actually useful to have multiple docker-credential-secretservice providers, I see that there is upstream this project: https://github.com/docker/docker-credential-helpers, would it be enough for most folks if the docker snap just contained those binaries on it's $PATH and we wait to add the content slot for generic providers until someone asks for a generic provider?

I admit it's not clear from the request whether doctl is itself a credential provider or not here, perhaps this request is indeed for a generic provider.

tianon commented 3 years ago

On Linux, the credential helpers are a little more complicated than places like OSX that have a core system keychain everything can rely on -- I believe the pass-based helper is the only one that works universally, and the usability of it is pretty bad. I think we could also consider the dbus-based secretservice, but I don't know much about it (or about the "D-Bus secret service" it's based on, nor what it would require for Docker to communicate with that inside Snappy).

Also note https://github.com/docker/docker-credential-helpers/releases -- that repository hasn't had a release in quite a while now (and commits on master aren't very promising either). I have a hard time believing it's so perfect it doesn't need any changes. :innocent:

andrewsomething commented 3 years ago

I admit it's not clear from the request whether doctl is itself a credential provider or not here, perhaps this request is indeed for a generic provider.

doctl interacts with the Docker credential store via https://godoc.org/github.com/docker/cli/cli/config/credentials#Store

By default, this will write to the configuration file. We have a personal-files connection for this. Though if the user has a credential-helper configured, it will attempt to use it and fail. (https://github.com/digitalocean/doctl/issues/876).

would it be enough for most folks if the docker snap just contained those binaries on it's $PATH

It sounds like that would probably be generally useful, but not solve doctl's specific use case. (Which might be fine!)


I think we could also consider the dbus-based secretservice, but I don't know much about it (or about the "D-Bus secret service" it's based on, nor what it would require for Docker to communicate with that inside Snappy).

It looks like it leverages libsecret (https://developer.gnome.org/libsecret/) which the password-manager-service-interface seems provide access to.

https://snapcraft.io/docs/password-manager-service-interface

typed-hole commented 2 years ago

I realized I have a need for this today, as I was trying to use the docker-credential-pass snap but realizing that the docker snap isn't allowed to access it (which makes me wonder what the purpose of the docker-credential-pass snap is, since this is the only use case I can imagine for it, but I realize it's owned/maintained by someone else)

Is anyone currently working on either of the solutions discussed above?

xnox commented 1 year ago

I don't know how any of these things work. So it would be interesting to hear how this should work. For example @samuelkarp seems to have something that would be cool to integrate. Would you like to collab on this?

tianon commented 1 year ago

Back when he worked at Amazon, Sam helped create a credential helper for their registry, but he no longer works at Amazon and probably doesn't have a lot of interest in credential helpers anymore. :sweat_smile:

The high-level gist of how credential helpers work is that the Docker CLI invokes them (as a third-party binary) when doing CLI commands like docker push in order to get the appropriate credentials from somewhere other than the base64'd storage it uses inside ~/.docker/config.json by default (which obviously isn't a terribly secure way to store sensitive information like passwords).