diff --git a/cmd/docker/docker.go b/cmd/docker/docker.go index 8b15b76f8ec7..1269f42734a1 100644 --- a/cmd/docker/docker.go +++ b/cmd/docker/docker.go @@ -29,6 +29,13 @@ import ( ) func main() { + // multi-call binary, if called as file credentials-helper + // then we exec the credhelper flow and exit + if os.Args[0] == fileCredsHelperBinary { + serveFileCredHelper() + return + } + err := dockerMain(context.Background()) if err != nil && !errdefs.IsCancelled(err) { _, _ = fmt.Fprintln(os.Stderr, err) diff --git a/cmd/docker/file_helper.go b/cmd/docker/file_helper.go new file mode 100644 index 000000000000..c44a47a882ee --- /dev/null +++ b/cmd/docker/file_helper.go @@ -0,0 +1,64 @@ +package main + +import ( + "os" + + credhelpers "github.com/docker/docker-credential-helpers/credentials" + + "github.com/docker/cli/cli/config" + "github.com/docker/cli/cli/config/credentials" + "github.com/docker/cli/cli/config/types" +) + +//nolint:gosec // ignore G101: Potential hardcoded credentials +const fileCredsHelperBinary = "docker-credential-file" + +func serveFileCredHelper() { + configfile := config.LoadDefaultConfigFile(os.Stderr) + store := credentials.NewFileStore(configfile) + credhelpers.Serve(&FileHelper{ + fileStore: store, + }) +} + +var _ credhelpers.Helper = &FileHelper{} + +type FileHelper struct { + fileStore credentials.Store +} + +func (f *FileHelper) Add(creds *credhelpers.Credentials) error { + return f.fileStore.Store(types.AuthConfig{ + Username: creds.Username, + Password: creds.Secret, + ServerAddress: creds.ServerURL, + }) +} + +func (f *FileHelper) Delete(serverAddress string) error { + return f.fileStore.Erase(serverAddress) +} + +func (f *FileHelper) Get(serverAddress string) (string, string, error) { + authConfig, err := f.fileStore.Get(serverAddress) + if err != nil { + return "", "", err + } + + return authConfig.Username, authConfig.Password, nil +} + +func (f *FileHelper) List() (map[string]string, error) { + creds := make(map[string]string) + + authConfig, err := f.fileStore.GetAll() + if err != nil { + return nil, err + } + + for k, v := range authConfig { + creds[k] = v.Username + } + + return creds, nil +}