cli/command: ResolveAuthConfig, GetDefaultAuthConfig: take ConfigFile as arg

Both these functions took the whole DockerCLI as argument, but only needed
the ConfigFile. ResolveAuthConfig also had an unused context.Context as
argument.

This patch updates both functions to accept a ConfigFile, and removes the
unused context.Context.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2023-07-10 17:24:07 +02:00
parent dc1359230f
commit 211220cbb0
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
15 changed files with 38 additions and 60 deletions

View File

@ -189,7 +189,7 @@ func (cli *DockerCli) ManifestStore() manifeststore.Store {
// registry
func (cli *DockerCli) RegistryClient(allowInsecure bool) registryclient.RegistryClient {
resolver := func(ctx context.Context, index *registry.IndexInfo) registry.AuthConfig {
return ResolveAuthConfig(ctx, cli, index)
return ResolveAuthConfig(cli.ConfigFile(), index)
}
return registryclient.NewRegistryClient(resolver, UserAgent(), allowInsecure)
}

View File

@ -114,7 +114,7 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, options *createOptio
// FIXME(thaJeztah): this is the only code-path that uses APIClient.ImageCreate. Rewrite this to use the regular "pull" code (or vice-versa).
func pullImage(ctx context.Context, dockerCli command.Cli, image string, opts *createOptions) error {
encodedAuth, err := command.RetrieveAuthTokenFromImage(ctx, dockerCli, image)
encodedAuth, err := command.RetrieveAuthTokenFromImage(dockerCli.ConfigFile(), image)
if err != nil {
return err
}

View File

@ -76,7 +76,7 @@ func RunPush(dockerCli command.Cli, opts pushOptions) error {
ctx := context.Background()
// Resolve the Auth config relevant for this server
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), repoInfo.Index)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil {
return err

View File

@ -339,6 +339,6 @@ func TagTrusted(ctx context.Context, cli command.Cli, trustedRef reference.Canon
// AuthResolver returns an auth resolver function from a command.Cli
func AuthResolver(cli command.Cli) func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
return func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
return command.ResolveAuthConfig(ctx, cli, index)
return command.ResolveAuthConfig(cli.ConfigFile(), index)
}
}

View File

@ -79,19 +79,18 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
return types.PluginInstallOptions{}, errors.Errorf("invalid name: %s", ref.String())
}
trusted, err := image.TrustedReference(context.Background(), dockerCli, nt)
trusted, err := image.TrustedReference(ctx, dockerCli, nt)
if err != nil {
return types.PluginInstallOptions{}, err
}
remote = reference.FamiliarString(trusted)
}
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), repoInfo.Index)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil {
return types.PluginInstallOptions{}, err
}
registryAuthFunc := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, cmdName)
options := types.PluginInstallOptions{
RegistryAuth: encodedAuth,
@ -99,7 +98,7 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
Disabled: opts.disable,
AcceptAllPermissions: opts.grantPerms,
AcceptPermissionsFunc: acceptPrivileges(dockerCli, opts.remote),
PrivilegeFunc: registryAuthFunc,
PrivilegeFunc: command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, cmdName),
Args: opts.args,
}
return options, nil

View File

@ -55,7 +55,7 @@ func runPush(dockerCli command.Cli, opts pushOptions) error {
if err != nil {
return err
}
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), repoInfo.Index)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil {
return err

View File

@ -2,13 +2,13 @@ package command
import (
"bufio"
"context"
"fmt"
"io"
"os"
"runtime"
"strings"
"github.com/docker/cli/cli/config/configfile"
configtypes "github.com/docker/cli/cli/config/types"
"github.com/docker/cli/cli/streams"
"github.com/docker/distribution/reference"
@ -26,7 +26,7 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
fmt.Fprintf(cli.Out(), "\nPlease login prior to %s:\n", cmdName)
indexServer := registry.GetAuthConfigKey(index)
isDefaultRegistry := indexServer == registry.IndexServer
authConfig, err := GetDefaultAuthConfig(cli, true, indexServer, isDefaultRegistry)
authConfig, err := GetDefaultAuthConfig(cli.ConfigFile(), true, indexServer, isDefaultRegistry)
if err != nil {
fmt.Fprintf(cli.Err(), "Unable to retrieve stored credentials for %s, error: %s.\n", indexServer, err)
}
@ -44,26 +44,26 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
//
// It is similar to [registry.ResolveAuthConfig], but uses the credentials-
// store, instead of looking up credentials from a map.
func ResolveAuthConfig(_ context.Context, cli Cli, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
configKey := index.Name
if index.Official {
configKey = registry.IndexServer
}
a, _ := cli.ConfigFile().GetAuthConfig(configKey)
a, _ := cfg.GetAuthConfig(configKey)
return registrytypes.AuthConfig(a)
}
// GetDefaultAuthConfig gets the default auth config given a serverAddress
// If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it
func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registrytypes.AuthConfig, error) {
func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registrytypes.AuthConfig, error) {
if !isDefaultRegistry {
serverAddress = registry.ConvertToHostname(serverAddress)
}
authconfig := configtypes.AuthConfig{}
var err error
if checkCredStore {
authconfig, err = cli.ConfigFile().GetAuthConfig(serverAddress)
authconfig, err = cfg.GetAuthConfig(serverAddress)
if err != nil {
return registrytypes.AuthConfig{
ServerAddress: serverAddress,
@ -72,8 +72,7 @@ func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, is
}
authconfig.ServerAddress = serverAddress
authconfig.IdentityToken = ""
res := registrytypes.AuthConfig(authconfig)
return res, nil
return registrytypes.AuthConfig(authconfig), nil
}
// ConfigureAuth handles prompting of user's username and password if needed
@ -172,9 +171,9 @@ func promptWithDefault(out io.Writer, prompt string, configDefault string) {
//
// For details on base64url encoding, see:
// - RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5
func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (string, error) {
func RetrieveAuthTokenFromImage(cfg *configfile.ConfigFile, image string) (string, error) {
// Retrieve encoded auth token from the image reference
authConfig, err := resolveAuthConfigFromImage(ctx, cli, image)
authConfig, err := resolveAuthConfigFromImage(cfg, image)
if err != nil {
return "", err
}
@ -186,7 +185,7 @@ func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (str
}
// resolveAuthConfigFromImage retrieves that AuthConfig using the image string
func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (registrytypes.AuthConfig, error) {
func resolveAuthConfigFromImage(cfg *configfile.ConfigFile, image string) (registrytypes.AuthConfig, error) {
registryRef, err := reference.ParseNormalizedNamed(image)
if err != nil {
return registrytypes.AuthConfig{}, err
@ -195,5 +194,5 @@ func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (reg
if err != nil {
return registrytypes.AuthConfig{}, err
}
return ResolveAuthConfig(ctx, cli, repoInfo.Index), nil
return ResolveAuthConfig(cfg, repoInfo.Index), nil
}

View File

@ -117,7 +117,7 @@ func runLogin(dockerCli command.Cli, opts loginOptions) error { //nolint:gocyclo
}
isDefaultRegistry := serverAddress == registry.IndexServer
authConfig, err := command.GetDefaultAuthConfig(dockerCli, opts.user == "" && opts.password == "", serverAddress, isDefaultRegistry)
authConfig, err := command.GetDefaultAuthConfig(dockerCli.ConfigFile(), opts.user == "" && opts.password == "", serverAddress, isDefaultRegistry)
if err == nil && authConfig.Username != "" && authConfig.Password != "" {
response, err = loginWithCredStoreCreds(ctx, dockerCli, &authConfig)
}

View File

@ -54,13 +54,13 @@ func runSearch(dockerCli command.Cli, options searchOptions) error {
return err
}
ctx := context.Background()
authConfig := command.ResolveAuthConfig(ctx, dockerCli, indexInfo)
authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), indexInfo)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil {
return err
}
ctx := context.Background()
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search")
results, err := dockerCli.Client().ImageSearch(ctx, options.term, types.ImageSearchOptions{
RegistryAuth: encodedAuth,

View File

@ -1,26 +1,17 @@
package command_test
import (
"bytes"
"context"
"fmt"
"testing"
. "github.com/docker/cli/cli/command" // Prevents a circular import with "github.com/docker/cli/internal/test"
"github.com/docker/cli/cli/config/configfile"
configtypes "github.com/docker/cli/cli/config/types"
"github.com/docker/cli/internal/test"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/api/types/system"
"github.com/docker/docker/client"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
)
type fakeClient struct {
client.Client
infoFunc func() (system.Info, error)
}
var testAuthConfigs = []registry.AuthConfig{
{
ServerAddress: "https://index.docker.io/v1/",
@ -34,13 +25,6 @@ var testAuthConfigs = []registry.AuthConfig{
},
}
func (cli *fakeClient) Info(_ context.Context) (system.Info, error) {
if cli.infoFunc != nil {
return cli.infoFunc()
}
return system.Info{}, nil
}
func TestGetDefaultAuthConfig(t *testing.T) {
testCases := []struct {
checkCredStore bool
@ -77,15 +61,13 @@ func TestGetDefaultAuthConfig(t *testing.T) {
expectedAuthConfig: testAuthConfigs[1],
},
}
cli := test.NewFakeCli(&fakeClient{})
errBuf := new(bytes.Buffer)
cli.SetErr(errBuf)
cfg := configfile.New("filename")
for _, authconfig := range testAuthConfigs {
cli.ConfigFile().GetCredentialsStore(authconfig.ServerAddress).Store(configtypes.AuthConfig(authconfig))
cfg.GetCredentialsStore(authconfig.ServerAddress).Store(configtypes.AuthConfig(authconfig))
}
for _, tc := range testCases {
serverAddress := tc.inputServerAddress
authconfig, err := GetDefaultAuthConfig(cli, tc.checkCredStore, serverAddress, serverAddress == "https://index.docker.io/v1/")
authconfig, err := GetDefaultAuthConfig(cfg, tc.checkCredStore, serverAddress, serverAddress == "https://index.docker.io/v1/")
if tc.expectedErr != "" {
assert.Check(t, err != nil)
assert.Check(t, is.Equal(tc.expectedErr, err.Error()))
@ -97,15 +79,14 @@ func TestGetDefaultAuthConfig(t *testing.T) {
}
func TestGetDefaultAuthConfig_HelperError(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
errBuf := new(bytes.Buffer)
cli.SetErr(errBuf)
cli.ConfigFile().CredentialsStore = "fake-does-not-exist"
serverAddress := "test-server-address"
cfg := configfile.New("filename")
cfg.CredentialsStore = "fake-does-not-exist"
const serverAddress = "test-server-address"
expectedAuthConfig := registry.AuthConfig{
ServerAddress: serverAddress,
}
authconfig, err := GetDefaultAuthConfig(cli, true, serverAddress, serverAddress == "https://index.docker.io/v1/")
authconfig, err := GetDefaultAuthConfig(cfg, true, serverAddress, serverAddress == "https://index.docker.io/v1/")
assert.Check(t, is.DeepEqual(expectedAuthConfig, authconfig))
assert.Check(t, is.ErrorContains(err, "docker-credential-fake-does-not-exist"))
}

View File

@ -112,7 +112,7 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *serviceOptions
// only send auth if flag was set
if opts.registryAuth {
// Retrieve encoded auth token from the image reference
encodedAuth, err := command.RetrieveAuthTokenFromImage(ctx, dockerCli, opts.image)
encodedAuth, err := command.RetrieveAuthTokenFromImage(dockerCli.ConfigFile(), opts.image)
if err != nil {
return err
}

View File

@ -1,7 +1,6 @@
package service
import (
"context"
"encoding/hex"
"github.com/docker/cli/cli/command"
@ -39,7 +38,7 @@ func resolveServiceImageDigestContentTrust(dockerCli command.Cli, service *swarm
return errors.New("failed to resolve image digest using content trust: reference is not tagged")
}
resolvedImage, err := trustedResolveDigest(context.Background(), dockerCli, taggedRef)
resolvedImage, err := trustedResolveDigest(dockerCli, taggedRef)
if err != nil {
return errors.Wrap(err, "failed to resolve image digest using content trust")
}
@ -51,13 +50,13 @@ func resolveServiceImageDigestContentTrust(dockerCli command.Cli, service *swarm
return nil
}
func trustedResolveDigest(ctx context.Context, cli command.Cli, ref reference.NamedTagged) (reference.Canonical, error) {
func trustedResolveDigest(cli command.Cli, ref reference.NamedTagged) (reference.Canonical, error) {
repoInfo, err := registry.ParseRepositoryInfo(ref)
if err != nil {
return nil, err
}
authConfig := command.ResolveAuthConfig(ctx, cli, repoInfo.Index)
authConfig := command.ResolveAuthConfig(cli.ConfigFile(), repoInfo.Index)
notaryRepo, err := trust.GetNotaryRepository(cli.In(), cli.Out(), command.UserAgent(), repoInfo, &authConfig, "pull")
if err != nil {

View File

@ -223,7 +223,7 @@ func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOpti
// Retrieve encoded auth token from the image reference
// This would be the old image if it didn't change in this update
image := spec.TaskTemplate.ContainerSpec.Image
encodedAuth, err := command.RetrieveAuthTokenFromImage(ctx, dockerCli, image)
encodedAuth, err := command.RetrieveAuthTokenFromImage(dockerCli.ConfigFile(), image)
if err != nil {
return err
}

View File

@ -198,7 +198,7 @@ func deployServices(ctx context.Context, dockerCli command.Cli, services map[str
if sendAuth {
// Retrieve encoded auth token from the image reference
encodedAuth, err = command.RetrieveAuthTokenFromImage(ctx, dockerCli, image)
encodedAuth, err = command.RetrieveAuthTokenFromImage(dockerCli.ConfigFile(), image)
if err != nil {
return err
}

View File

@ -93,7 +93,7 @@ func runSignImage(cli command.Cli, options signOptions) error {
}
fmt.Fprintf(cli.Err(), "Signing and pushing trust data for local image %s, may overwrite remote trust data\n", imageName)
authConfig := command.ResolveAuthConfig(ctx, cli, imgRefAndAuth.RepoInfo().Index)
authConfig := command.ResolveAuthConfig(cli.ConfigFile(), imgRefAndAuth.RepoInfo().Index)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil {
return err