Merge pull request #4412 from thaJeztah/auth_use_config

cli/command: ResolveAuthConfig, GetDefaultAuthConfig: take ConfigFile as arg
This commit is contained in:
Sebastiaan van Stijn 2023-08-08 22:01:13 +02:00 committed by GitHub
commit 0c5eb94eb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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