-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Historically Docker has relied upon the docker-credential-helper which ships with Docker Desktop.
The docker-credential-helper is a separate binary and is always invoked as a separate binary due to the limitations of the OS keystore. As far as I am aware, macOS has a limitation that when writing a credential to the keystore it is only retrievable by the same binary. So storing a credential in the Docker CLI will only be retrievable by the Docker CLI.
With what does it integrate?
Depending on the OS, the docker-credential-helper integrates with:
- libsecret on Linux
- pass on Linux
- keybase/go-keychain on macOS
- danieljoos/wincred on Windows
In the past the docker-credential-helper used to integrate directly with the macOS Security/Security.h C library, but was swapped for the keybase/go-keychain library in this commit docker/docker-credential-helpers@4cdcdc2 due to deprecated SDK functions in osx docker/docker-credential-helpers#280.
The credential helper also usually ships the pass implementation and not the libsecret implementation. The pass implementation was added here docker/docker-credential-helpers#81 to support use cases where the user does not have a GUI installed (e.g. server environments).
Why not just use the credential helper?
The credential helper is very tied to the concept of a registry. Each credential stored is using a ServerURL to indicate which registry is saving the credential. You can see this in our schema defined for the libsecret implementation over here
Over time we have started moving away from registry authentication to other types of authentication like OAuth (Docker Hub login). This means that a login is based on a realm or namespace and multiple users could be saved under a realm / namespace.
Doing an exec out to the binary is annoying. It gives little control to the library implementing the credential-helper - we even have to rely on the user to install this (in certain environments) and we rely on the config specifying the correct credential-helper.
- This is a confusing UX to the user
- Other software can change the config
- Requires installing another binary
Why in Secrets Engine?
We want a re-usable keystore library that can be consumed by tools within Docker. The Secrets engine will be the main point of contact for most tools within Docker as each tool will also have a provider interface with the Secrets Engine to retrieve secrets from a keystore.
We could do it in a separate repository, but keeping it here will enable us to be fast when iterating and we can always move it out when needed.
What do we want to use for MacOS?
Since we already know that keybase/go-keychain works with docker-credential-helper, possibly sticking with it would be OK. It is unclear if keybase/go-keychain is really maintained, but it is widely used, so we wouldn't be the only ones complaining if it breaks.
What do we want to use for Linux?
It seems like a safe bet is to use libsecret. It supports calling the freedesktop secrets service and falling back to an encrypted file if not available.
We should call org.freedesktop.secrets over DBUS using keybase/go-keychain. The fallback libsecret provides is still reliant on the user having a GUI because of the reliance on org.freedesktop.portal.
What do we want to use for Windows?
We'll use https://github.com/danieljoos/wincred
Fallback store
A fallback store should be self-contained, easy to use and secure. The current credential helper fails at providing a self-contained store, it relies on pass which relies on gpg and is only Linux based. Credentials should always be encrypted and shouldn't require any setup or init run to get started. Users should also not need any additional tools to use it.
A library that could fit this scenario is age. It is a well-known library for file encryption and can be extended to support more niche cases if we need to (e.g. support Yubikeys).
Prior Art
- https://github.com/99designs/keyring
- https://github.com/zalando/go-keyring
- https://github.com/keybase/go-keychain/
Some interesting issues on the Credential Helper
- fix(wincred): Encode passwords to UTF-16 docker-credential-helpers#335
- feat: add support for gopass as a credential store docker-credential-helpers#268
- Enable secretservice on non-linux systems docker-credential-helpers#228
- Fix issue #162 (docker-credential-pass does not work with username containing forward-slash) docker-credential-helpers#267
- pass: base64 encoded username with backward compatility docker-credential-helpers#288
- Unable to authenticate with container registry using pass docker-credential-helpers#354
- pass: docker login does not work after rotating gpg key docker-credential-helpers#299
- Inconsistent auth keys on macOS, Windows, Linux docker-credential-helpers#256