mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Move CLI config processing out from under registry dir
No logic changes should be in here, just moving things around. Signed-off-by: Doug Davis <dug@us.ibm.com>
This commit is contained in:
		
							parent
							
								
									fa3e2dd45e
								
							
						
					
					
						commit
						bb9da6ba92
					
				
					 19 changed files with 301 additions and 269 deletions
				
			
		| 
						 | 
				
			
			@ -15,10 +15,10 @@ import (
 | 
			
		|||
	"text/template"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	"github.com/docker/docker/pkg/homedir"
 | 
			
		||||
	flag "github.com/docker/docker/pkg/mflag"
 | 
			
		||||
	"github.com/docker/docker/pkg/term"
 | 
			
		||||
	"github.com/docker/docker/registry"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DockerCli represents the docker command line client.
 | 
			
		||||
| 
						 | 
				
			
			@ -28,8 +28,9 @@ type DockerCli struct {
 | 
			
		|||
	proto string
 | 
			
		||||
	// addr holds the client address.
 | 
			
		||||
	addr string
 | 
			
		||||
	// configFile holds the configuration file (instance of registry.ConfigFile).
 | 
			
		||||
	configFile *registry.ConfigFile
 | 
			
		||||
 | 
			
		||||
	// configFile has the client configuration file
 | 
			
		||||
	configFile *cliconfig.ConfigFile
 | 
			
		||||
	// in holds the input stream and closer (io.ReadCloser) for the client.
 | 
			
		||||
	in io.ReadCloser
 | 
			
		||||
	// out holds the output stream (io.Writer) for the client.
 | 
			
		||||
| 
						 | 
				
			
			@ -184,7 +185,7 @@ func NewDockerCli(in io.ReadCloser, out, err io.Writer, keyFile string, proto, a
 | 
			
		|||
		tr.Dial = (&net.Dialer{Timeout: timeout}).Dial
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	configFile, e := registry.LoadConfig(filepath.Join(homedir.Get(), ".docker"))
 | 
			
		||||
	configFile, e := cliconfig.Load(filepath.Join(homedir.Get(), ".docker"))
 | 
			
		||||
	if e != nil {
 | 
			
		||||
		fmt.Fprintf(err, "WARNING: Error loading config file:%v\n", e)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ func (cli *DockerCli) pullImageCustomOut(image string, out io.Writer) error {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Resolve the Auth config relevant for this server
 | 
			
		||||
	authConfig := cli.configFile.ResolveAuthConfig(repoInfo.Index)
 | 
			
		||||
	authConfig := registry.ResolveAuthConfig(cli.configFile, repoInfo.Index)
 | 
			
		||||
	buf, err := json.Marshal(authConfig)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	flag "github.com/docker/docker/pkg/mflag"
 | 
			
		||||
	"github.com/docker/docker/pkg/term"
 | 
			
		||||
	"github.com/docker/docker/registry"
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +57,7 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
 | 
			
		|||
 | 
			
		||||
	authconfig, ok := cli.configFile.AuthConfigs[serverAddress]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		authconfig = registry.AuthConfig{}
 | 
			
		||||
		authconfig = cliconfig.AuthConfig{}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if username == "" {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ func (cli *DockerCli) CmdPush(args ...string) error {
 | 
			
		|||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	// Resolve the Auth config relevant for this server
 | 
			
		||||
	authConfig := cli.configFile.ResolveAuthConfig(repoInfo.Index)
 | 
			
		||||
	authConfig := registry.ResolveAuthConfig(cli.configFile, repoInfo.Index)
 | 
			
		||||
	// If we're not using a custom registry, we know the restrictions
 | 
			
		||||
	// applied to repository names and can warn the user in advance.
 | 
			
		||||
	// Custom repositories can have different rules, and we must also
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,7 @@ import (
 | 
			
		|||
	"github.com/docker/docker/api"
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/autogen/dockerversion"
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	"github.com/docker/docker/engine"
 | 
			
		||||
	"github.com/docker/docker/pkg/jsonmessage"
 | 
			
		||||
	"github.com/docker/docker/pkg/signal"
 | 
			
		||||
| 
						 | 
				
			
			@ -119,7 +120,7 @@ func (cli *DockerCli) clientRequest(method, path string, in io.Reader, headers m
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (cli *DockerCli) clientRequestAttemptLogin(method, path string, in io.Reader, out io.Writer, index *registry.IndexInfo, cmdName string) (io.ReadCloser, int, error) {
 | 
			
		||||
	cmdAttempt := func(authConfig registry.AuthConfig) (io.ReadCloser, int, error) {
 | 
			
		||||
	cmdAttempt := func(authConfig cliconfig.AuthConfig) (io.ReadCloser, int, error) {
 | 
			
		||||
		buf, err := json.Marshal(authConfig)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, -1, err
 | 
			
		||||
| 
						 | 
				
			
			@ -150,14 +151,14 @@ func (cli *DockerCli) clientRequestAttemptLogin(method, path string, in io.Reade
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Resolve the Auth config relevant for this server
 | 
			
		||||
	authConfig := cli.configFile.ResolveAuthConfig(index)
 | 
			
		||||
	authConfig := registry.ResolveAuthConfig(cli.configFile, index)
 | 
			
		||||
	body, statusCode, err := cmdAttempt(authConfig)
 | 
			
		||||
	if statusCode == http.StatusUnauthorized {
 | 
			
		||||
		fmt.Fprintf(cli.out, "\nPlease login prior to %s:\n", cmdName)
 | 
			
		||||
		if err = cli.CmdLogin(index.GetAuthConfigKey()); err != nil {
 | 
			
		||||
			return nil, -1, err
 | 
			
		||||
		}
 | 
			
		||||
		authConfig = cli.configFile.ResolveAuthConfig(index)
 | 
			
		||||
		authConfig = registry.ResolveAuthConfig(cli.configFile, index)
 | 
			
		||||
		return cmdAttempt(authConfig)
 | 
			
		||||
	}
 | 
			
		||||
	return body, statusCode, err
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ import (
 | 
			
		|||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/autogen/dockerversion"
 | 
			
		||||
	"github.com/docker/docker/builder"
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	"github.com/docker/docker/daemon"
 | 
			
		||||
	"github.com/docker/docker/daemon/networkdriver/bridge"
 | 
			
		||||
	"github.com/docker/docker/engine"
 | 
			
		||||
| 
						 | 
				
			
			@ -34,7 +35,6 @@ import (
 | 
			
		|||
	"github.com/docker/docker/pkg/stdcopy"
 | 
			
		||||
	"github.com/docker/docker/pkg/streamformatter"
 | 
			
		||||
	"github.com/docker/docker/pkg/version"
 | 
			
		||||
	"github.com/docker/docker/registry"
 | 
			
		||||
	"github.com/docker/docker/runconfig"
 | 
			
		||||
	"github.com/docker/docker/utils"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -239,7 +239,7 @@ func streamJSON(out *engine.Output, w http.ResponseWriter, flush bool) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (s *Server) postAuth(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 | 
			
		||||
	var config *registry.AuthConfig
 | 
			
		||||
	var config *cliconfig.AuthConfig
 | 
			
		||||
	err := json.NewDecoder(r.Body).Decode(&config)
 | 
			
		||||
	r.Body.Close()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -728,13 +728,13 @@ func (s *Server) postImagesCreate(eng *engine.Engine, version version.Version, w
 | 
			
		|||
		tag   = r.Form.Get("tag")
 | 
			
		||||
	)
 | 
			
		||||
	authEncoded := r.Header.Get("X-Registry-Auth")
 | 
			
		||||
	authConfig := ®istry.AuthConfig{}
 | 
			
		||||
	authConfig := &cliconfig.AuthConfig{}
 | 
			
		||||
	if authEncoded != "" {
 | 
			
		||||
		authJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
 | 
			
		||||
		if err := json.NewDecoder(authJson).Decode(authConfig); err != nil {
 | 
			
		||||
			// for a pull it is not an error if no auth was given
 | 
			
		||||
			// to increase compatibility with the existing api it is defaulting to be empty
 | 
			
		||||
			authConfig = ®istry.AuthConfig{}
 | 
			
		||||
			authConfig = &cliconfig.AuthConfig{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -802,7 +802,7 @@ func (s *Server) getImagesSearch(eng *engine.Engine, version version.Version, w
 | 
			
		|||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	var (
 | 
			
		||||
		config      *registry.AuthConfig
 | 
			
		||||
		config      *cliconfig.AuthConfig
 | 
			
		||||
		authEncoded = r.Header.Get("X-Registry-Auth")
 | 
			
		||||
		headers     = map[string][]string{}
 | 
			
		||||
	)
 | 
			
		||||
| 
						 | 
				
			
			@ -812,7 +812,7 @@ func (s *Server) getImagesSearch(eng *engine.Engine, version version.Version, w
 | 
			
		|||
		if err := json.NewDecoder(authJson).Decode(&config); err != nil {
 | 
			
		||||
			// for a search it is not an error if no auth was given
 | 
			
		||||
			// to increase compatibility with the existing api it is defaulting to be empty
 | 
			
		||||
			config = ®istry.AuthConfig{}
 | 
			
		||||
			config = &cliconfig.AuthConfig{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for k, v := range r.Header {
 | 
			
		||||
| 
						 | 
				
			
			@ -841,7 +841,7 @@ func (s *Server) postImagesPush(eng *engine.Engine, version version.Version, w h
 | 
			
		|||
	if err := parseForm(r); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	authConfig := ®istry.AuthConfig{}
 | 
			
		||||
	authConfig := &cliconfig.AuthConfig{}
 | 
			
		||||
 | 
			
		||||
	authEncoded := r.Header.Get("X-Registry-Auth")
 | 
			
		||||
	if authEncoded != "" {
 | 
			
		||||
| 
						 | 
				
			
			@ -849,7 +849,7 @@ func (s *Server) postImagesPush(eng *engine.Engine, version version.Version, w h
 | 
			
		|||
		authJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
 | 
			
		||||
		if err := json.NewDecoder(authJson).Decode(authConfig); err != nil {
 | 
			
		||||
			// to increase compatibility to existing api it is defaulting to be empty
 | 
			
		||||
			authConfig = ®istry.AuthConfig{}
 | 
			
		||||
			authConfig = &cliconfig.AuthConfig{}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		// the old format is supported for compatibility if there was no authConfig header
 | 
			
		||||
| 
						 | 
				
			
			@ -1263,9 +1263,9 @@ func (s *Server) postBuild(eng *engine.Engine, version version.Version, w http.R
 | 
			
		|||
	}
 | 
			
		||||
	var (
 | 
			
		||||
		authEncoded       = r.Header.Get("X-Registry-Auth")
 | 
			
		||||
		authConfig        = ®istry.AuthConfig{}
 | 
			
		||||
		authConfig        = &cliconfig.AuthConfig{}
 | 
			
		||||
		configFileEncoded = r.Header.Get("X-Registry-Config")
 | 
			
		||||
		configFile        = ®istry.ConfigFile{}
 | 
			
		||||
		configFile        = &cliconfig.ConfigFile{}
 | 
			
		||||
		buildConfig       = builder.NewBuildConfig()
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1278,7 +1278,7 @@ func (s *Server) postBuild(eng *engine.Engine, version version.Version, w http.R
 | 
			
		|||
		if err := json.NewDecoder(authJson).Decode(authConfig); err != nil {
 | 
			
		||||
			// for a pull it is not an error if no auth was given
 | 
			
		||||
			// to increase compatibility with the existing api it is defaulting to be empty
 | 
			
		||||
			authConfig = ®istry.AuthConfig{}
 | 
			
		||||
			authConfig = &cliconfig.AuthConfig{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1287,7 +1287,7 @@ func (s *Server) postBuild(eng *engine.Engine, version version.Version, w http.R
 | 
			
		|||
		if err := json.NewDecoder(configFileJson).Decode(configFile); err != nil {
 | 
			
		||||
			// for a pull it is not an error if no auth was given
 | 
			
		||||
			// to increase compatibility with the existing api it is defaulting to be empty
 | 
			
		||||
			configFile = ®istry.ConfigFile{}
 | 
			
		||||
			configFile = &cliconfig.ConfigFile{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,13 +30,13 @@ import (
 | 
			
		|||
	"github.com/docker/docker/api"
 | 
			
		||||
	"github.com/docker/docker/builder/command"
 | 
			
		||||
	"github.com/docker/docker/builder/parser"
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	"github.com/docker/docker/daemon"
 | 
			
		||||
	"github.com/docker/docker/pkg/fileutils"
 | 
			
		||||
	"github.com/docker/docker/pkg/streamformatter"
 | 
			
		||||
	"github.com/docker/docker/pkg/stringid"
 | 
			
		||||
	"github.com/docker/docker/pkg/symlink"
 | 
			
		||||
	"github.com/docker/docker/pkg/tarsum"
 | 
			
		||||
	"github.com/docker/docker/registry"
 | 
			
		||||
	"github.com/docker/docker/runconfig"
 | 
			
		||||
	"github.com/docker/docker/utils"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -99,8 +99,8 @@ type Builder struct {
 | 
			
		|||
	// the final configs of the Dockerfile but dont want the layers
 | 
			
		||||
	disableCommit bool
 | 
			
		||||
 | 
			
		||||
	AuthConfig *registry.AuthConfig
 | 
			
		||||
	ConfigFile *registry.ConfigFile
 | 
			
		||||
	AuthConfig *cliconfig.AuthConfig
 | 
			
		||||
	ConfigFile *cliconfig.ConfigFile
 | 
			
		||||
 | 
			
		||||
	// Deprecated, original writer used for ImagePull. To be removed.
 | 
			
		||||
	OutOld          io.Writer
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,6 +36,7 @@ import (
 | 
			
		|||
	"github.com/docker/docker/pkg/system"
 | 
			
		||||
	"github.com/docker/docker/pkg/tarsum"
 | 
			
		||||
	"github.com/docker/docker/pkg/urlutil"
 | 
			
		||||
	"github.com/docker/docker/registry"
 | 
			
		||||
	"github.com/docker/docker/runconfig"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -443,7 +444,7 @@ func (b *Builder) pullImage(name string) (*imagepkg.Image, error) {
 | 
			
		|||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		resolvedAuth := b.ConfigFile.ResolveAuthConfig(repoInfo.Index)
 | 
			
		||||
		resolvedAuth := registry.ResolveAuthConfig(b.ConfigFile, repoInfo.Index)
 | 
			
		||||
		pullRegistryAuth = &resolvedAuth
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ import (
 | 
			
		|||
 | 
			
		||||
	"github.com/docker/docker/api"
 | 
			
		||||
	"github.com/docker/docker/builder/parser"
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	"github.com/docker/docker/daemon"
 | 
			
		||||
	"github.com/docker/docker/graph"
 | 
			
		||||
	"github.com/docker/docker/pkg/archive"
 | 
			
		||||
| 
						 | 
				
			
			@ -50,8 +51,8 @@ type Config struct {
 | 
			
		|||
	CpuShares      int64
 | 
			
		||||
	CpuSetCpus     string
 | 
			
		||||
	CpuSetMems     string
 | 
			
		||||
	AuthConfig     *registry.AuthConfig
 | 
			
		||||
	ConfigFile     *registry.ConfigFile
 | 
			
		||||
	AuthConfig     *cliconfig.AuthConfig
 | 
			
		||||
	ConfigFile     *cliconfig.ConfigFile
 | 
			
		||||
 | 
			
		||||
	Stdout  io.Writer
 | 
			
		||||
	Context io.ReadCloser
 | 
			
		||||
| 
						 | 
				
			
			@ -76,8 +77,8 @@ func (b *Config) WaitCancelled() <-chan struct{} {
 | 
			
		|||
 | 
			
		||||
func NewBuildConfig() *Config {
 | 
			
		||||
	return &Config{
 | 
			
		||||
		AuthConfig: ®istry.AuthConfig{},
 | 
			
		||||
		ConfigFile: ®istry.ConfigFile{},
 | 
			
		||||
		AuthConfig: &cliconfig.AuthConfig{},
 | 
			
		||||
		ConfigFile: &cliconfig.ConfigFile{},
 | 
			
		||||
		cancelled:  make(chan struct{}),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										208
									
								
								cliconfig/config.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								cliconfig/config.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,208 @@
 | 
			
		|||
package cliconfig
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/pkg/homedir"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// Where we store the config file
 | 
			
		||||
	CONFIGFILE     = "config.json"
 | 
			
		||||
	OLD_CONFIGFILE = ".dockercfg"
 | 
			
		||||
 | 
			
		||||
	// This constant is only used for really old config files when the
 | 
			
		||||
	// URL wasn't saved as part of the config file and it was just
 | 
			
		||||
	// assumed to be this value.
 | 
			
		||||
	DEFAULT_INDEXSERVER = "https://index.docker.io/v1/"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	ErrConfigFileMissing = errors.New("The Auth config file is missing")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Registry Auth Info
 | 
			
		||||
type AuthConfig struct {
 | 
			
		||||
	Username      string `json:"username,omitempty"`
 | 
			
		||||
	Password      string `json:"password,omitempty"`
 | 
			
		||||
	Auth          string `json:"auth"`
 | 
			
		||||
	Email         string `json:"email"`
 | 
			
		||||
	ServerAddress string `json:"serveraddress,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ~/.docker/config.json file info
 | 
			
		||||
type ConfigFile struct {
 | 
			
		||||
	AuthConfigs map[string]AuthConfig `json:"auths"`
 | 
			
		||||
	HttpHeaders map[string]string     `json:"HttpHeaders,omitempty"`
 | 
			
		||||
	filename    string                // Note: not serialized - for internal use only
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewConfigFile(fn string) *ConfigFile {
 | 
			
		||||
	return &ConfigFile{
 | 
			
		||||
		AuthConfigs: make(map[string]AuthConfig),
 | 
			
		||||
		HttpHeaders: make(map[string]string),
 | 
			
		||||
		filename:    fn,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// load up the auth config information and return values
 | 
			
		||||
// FIXME: use the internal golang config parser
 | 
			
		||||
func Load(configDir string) (*ConfigFile, error) {
 | 
			
		||||
	if configDir == "" {
 | 
			
		||||
		configDir = filepath.Join(homedir.Get(), ".docker")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	configFile := ConfigFile{
 | 
			
		||||
		AuthConfigs: make(map[string]AuthConfig),
 | 
			
		||||
		filename:    filepath.Join(configDir, CONFIGFILE),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Try happy path first - latest config file
 | 
			
		||||
	if _, err := os.Stat(configFile.filename); err == nil {
 | 
			
		||||
		file, err := os.Open(configFile.filename)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return &configFile, err
 | 
			
		||||
		}
 | 
			
		||||
		defer file.Close()
 | 
			
		||||
 | 
			
		||||
		if err := json.NewDecoder(file).Decode(&configFile); err != nil {
 | 
			
		||||
			return &configFile, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for addr, ac := range configFile.AuthConfigs {
 | 
			
		||||
			ac.Username, ac.Password, err = DecodeAuth(ac.Auth)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return &configFile, err
 | 
			
		||||
			}
 | 
			
		||||
			ac.Auth = ""
 | 
			
		||||
			ac.ServerAddress = addr
 | 
			
		||||
			configFile.AuthConfigs[addr] = ac
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return &configFile, nil
 | 
			
		||||
	} else if !os.IsNotExist(err) {
 | 
			
		||||
		// if file is there but we can't stat it for any reason other
 | 
			
		||||
		// than it doesn't exist then stop
 | 
			
		||||
		return &configFile, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Can't find latest config file so check for the old one
 | 
			
		||||
	confFile := filepath.Join(homedir.Get(), OLD_CONFIGFILE)
 | 
			
		||||
 | 
			
		||||
	if _, err := os.Stat(confFile); err != nil {
 | 
			
		||||
		return &configFile, nil //missing file is not an error
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b, err := ioutil.ReadFile(confFile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return &configFile, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := json.Unmarshal(b, &configFile.AuthConfigs); err != nil {
 | 
			
		||||
		arr := strings.Split(string(b), "\n")
 | 
			
		||||
		if len(arr) < 2 {
 | 
			
		||||
			return &configFile, fmt.Errorf("The Auth config file is empty")
 | 
			
		||||
		}
 | 
			
		||||
		authConfig := AuthConfig{}
 | 
			
		||||
		origAuth := strings.Split(arr[0], " = ")
 | 
			
		||||
		if len(origAuth) != 2 {
 | 
			
		||||
			return &configFile, fmt.Errorf("Invalid Auth config file")
 | 
			
		||||
		}
 | 
			
		||||
		authConfig.Username, authConfig.Password, err = DecodeAuth(origAuth[1])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return &configFile, err
 | 
			
		||||
		}
 | 
			
		||||
		origEmail := strings.Split(arr[1], " = ")
 | 
			
		||||
		if len(origEmail) != 2 {
 | 
			
		||||
			return &configFile, fmt.Errorf("Invalid Auth config file")
 | 
			
		||||
		}
 | 
			
		||||
		authConfig.Email = origEmail[1]
 | 
			
		||||
		authConfig.ServerAddress = DEFAULT_INDEXSERVER
 | 
			
		||||
		configFile.AuthConfigs[DEFAULT_INDEXSERVER] = authConfig
 | 
			
		||||
	} else {
 | 
			
		||||
		for k, authConfig := range configFile.AuthConfigs {
 | 
			
		||||
			authConfig.Username, authConfig.Password, err = DecodeAuth(authConfig.Auth)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return &configFile, err
 | 
			
		||||
			}
 | 
			
		||||
			authConfig.Auth = ""
 | 
			
		||||
			authConfig.ServerAddress = k
 | 
			
		||||
			configFile.AuthConfigs[k] = authConfig
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return &configFile, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (configFile *ConfigFile) Save() error {
 | 
			
		||||
	// Encode sensitive data into a new/temp struct
 | 
			
		||||
	tmpAuthConfigs := make(map[string]AuthConfig, len(configFile.AuthConfigs))
 | 
			
		||||
	for k, authConfig := range configFile.AuthConfigs {
 | 
			
		||||
		authCopy := authConfig
 | 
			
		||||
 | 
			
		||||
		authCopy.Auth = EncodeAuth(&authCopy)
 | 
			
		||||
		authCopy.Username = ""
 | 
			
		||||
		authCopy.Password = ""
 | 
			
		||||
		authCopy.ServerAddress = ""
 | 
			
		||||
		tmpAuthConfigs[k] = authCopy
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	saveAuthConfigs := configFile.AuthConfigs
 | 
			
		||||
	configFile.AuthConfigs = tmpAuthConfigs
 | 
			
		||||
	defer func() { configFile.AuthConfigs = saveAuthConfigs }()
 | 
			
		||||
 | 
			
		||||
	data, err := json.MarshalIndent(configFile, "", "\t")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := os.MkdirAll(filepath.Dir(configFile.filename), 0700); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = ioutil.WriteFile(configFile.filename, data, 0600)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (config *ConfigFile) Filename() string {
 | 
			
		||||
	return config.filename
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// create a base64 encoded auth string to store in config
 | 
			
		||||
func EncodeAuth(authConfig *AuthConfig) string {
 | 
			
		||||
	authStr := authConfig.Username + ":" + authConfig.Password
 | 
			
		||||
	msg := []byte(authStr)
 | 
			
		||||
	encoded := make([]byte, base64.StdEncoding.EncodedLen(len(msg)))
 | 
			
		||||
	base64.StdEncoding.Encode(encoded, msg)
 | 
			
		||||
	return string(encoded)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// decode the auth string
 | 
			
		||||
func DecodeAuth(authStr string) (string, string, error) {
 | 
			
		||||
	decLen := base64.StdEncoding.DecodedLen(len(authStr))
 | 
			
		||||
	decoded := make([]byte, decLen)
 | 
			
		||||
	authByte := []byte(authStr)
 | 
			
		||||
	n, err := base64.StdEncoding.Decode(decoded, authByte)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", "", err
 | 
			
		||||
	}
 | 
			
		||||
	if n > decLen {
 | 
			
		||||
		return "", "", fmt.Errorf("Something went wrong decoding auth config")
 | 
			
		||||
	}
 | 
			
		||||
	arr := strings.SplitN(string(decoded), ":", 2)
 | 
			
		||||
	if len(arr) != 2 {
 | 
			
		||||
		return "", "", fmt.Errorf("Invalid auth configuration file")
 | 
			
		||||
	}
 | 
			
		||||
	password := strings.Trim(arr[1], "\x00")
 | 
			
		||||
	return arr[0], password, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package registry
 | 
			
		||||
package cliconfig
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ import (
 | 
			
		|||
func TestMissingFile(t *testing.T) {
 | 
			
		||||
	tmpHome, _ := ioutil.TempDir("", "config-test")
 | 
			
		||||
 | 
			
		||||
	config, err := LoadConfig(tmpHome)
 | 
			
		||||
	config, err := Load(tmpHome)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed loading on missing file: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +36,7 @@ func TestSaveFileToDirs(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	tmpHome += "/.docker"
 | 
			
		||||
 | 
			
		||||
	config, err := LoadConfig(tmpHome)
 | 
			
		||||
	config, err := Load(tmpHome)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed loading on missing file: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +58,7 @@ func TestEmptyFile(t *testing.T) {
 | 
			
		|||
	fn := filepath.Join(tmpHome, CONFIGFILE)
 | 
			
		||||
	ioutil.WriteFile(fn, []byte(""), 0600)
 | 
			
		||||
 | 
			
		||||
	_, err := LoadConfig(tmpHome)
 | 
			
		||||
	_, err := Load(tmpHome)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		t.Fatalf("Was supposed to fail")
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -69,7 +69,7 @@ func TestEmptyJson(t *testing.T) {
 | 
			
		|||
	fn := filepath.Join(tmpHome, CONFIGFILE)
 | 
			
		||||
	ioutil.WriteFile(fn, []byte("{}"), 0600)
 | 
			
		||||
 | 
			
		||||
	config, err := LoadConfig(tmpHome)
 | 
			
		||||
	config, err := Load(tmpHome)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed loading on empty json file: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -104,7 +104,7 @@ func TestOldJson(t *testing.T) {
 | 
			
		|||
	js := `{"https://index.docker.io/v1/":{"auth":"am9lam9lOmhlbGxv","email":"user@example.com"}}`
 | 
			
		||||
	ioutil.WriteFile(fn, []byte(js), 0600)
 | 
			
		||||
 | 
			
		||||
	config, err := LoadConfig(tmpHome)
 | 
			
		||||
	config, err := Load(tmpHome)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed loading on empty json file: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -133,7 +133,7 @@ func TestNewJson(t *testing.T) {
 | 
			
		|||
	js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } } }`
 | 
			
		||||
	ioutil.WriteFile(fn, []byte(js), 0600)
 | 
			
		||||
 | 
			
		||||
	config, err := LoadConfig(tmpHome)
 | 
			
		||||
	config, err := Load(tmpHome)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed loading on empty json file: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ import (
 | 
			
		|||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	"github.com/docker/docker/image"
 | 
			
		||||
	"github.com/docker/docker/pkg/progressreader"
 | 
			
		||||
	"github.com/docker/docker/pkg/streamformatter"
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +24,7 @@ import (
 | 
			
		|||
type ImagePullConfig struct {
 | 
			
		||||
	Parallel    bool
 | 
			
		||||
	MetaHeaders map[string][]string
 | 
			
		||||
	AuthConfig  *registry.AuthConfig
 | 
			
		||||
	AuthConfig  *cliconfig.AuthConfig
 | 
			
		||||
	Json        bool
 | 
			
		||||
	OutStream   io.Writer
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ import (
 | 
			
		|||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	"github.com/docker/docker/image"
 | 
			
		||||
	"github.com/docker/docker/pkg/progressreader"
 | 
			
		||||
	"github.com/docker/docker/pkg/streamformatter"
 | 
			
		||||
| 
						 | 
				
			
			@ -26,7 +27,7 @@ var ErrV2RegistryUnavailable = errors.New("error v2 registry unavailable")
 | 
			
		|||
 | 
			
		||||
type ImagePushConfig struct {
 | 
			
		||||
	MetaHeaders map[string][]string
 | 
			
		||||
	AuthConfig  *registry.AuthConfig
 | 
			
		||||
	AuthConfig  *cliconfig.AuthConfig
 | 
			
		||||
	Tag         string
 | 
			
		||||
	Json        bool
 | 
			
		||||
	OutStream   io.Writer
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@ import (
 | 
			
		|||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	apiserver "github.com/docker/docker/api/server"
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	"github.com/docker/docker/daemon"
 | 
			
		||||
	"github.com/docker/docker/daemon/execdriver"
 | 
			
		||||
	"github.com/docker/docker/engine"
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +29,6 @@ import (
 | 
			
		|||
	"github.com/docker/docker/pkg/ioutils"
 | 
			
		||||
	"github.com/docker/docker/pkg/reexec"
 | 
			
		||||
	"github.com/docker/docker/pkg/stringid"
 | 
			
		||||
	"github.com/docker/docker/registry"
 | 
			
		||||
	"github.com/docker/docker/runconfig"
 | 
			
		||||
	"github.com/docker/docker/utils"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +135,7 @@ func setupBaseImage() {
 | 
			
		|||
		imagePullConfig := &graph.ImagePullConfig{
 | 
			
		||||
			Parallel:   true,
 | 
			
		||||
			OutStream:  ioutils.NopWriteCloser(os.Stdout),
 | 
			
		||||
			AuthConfig: ®istry.AuthConfig{},
 | 
			
		||||
			AuthConfig: &cliconfig.AuthConfig{},
 | 
			
		||||
		}
 | 
			
		||||
		d := getDaemon(eng)
 | 
			
		||||
		if err := d.Repositories().Pull(unitTestImageName, "", imagePullConfig); err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										210
									
								
								registry/auth.go
									
										
									
									
									
								
							
							
						
						
									
										210
									
								
								registry/auth.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,51 +1,21 @@
 | 
			
		|||
package registry
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/docker/pkg/homedir"
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	"github.com/docker/docker/pkg/requestdecorator"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// Where we store the config file
 | 
			
		||||
	CONFIGFILE     = "config.json"
 | 
			
		||||
	OLD_CONFIGFILE = ".dockercfg"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	ErrConfigFileMissing = errors.New("The Auth config file is missing")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Registry Auth Info
 | 
			
		||||
type AuthConfig struct {
 | 
			
		||||
	Username      string `json:"username,omitempty"`
 | 
			
		||||
	Password      string `json:"password,omitempty"`
 | 
			
		||||
	Auth          string `json:"auth"`
 | 
			
		||||
	Email         string `json:"email"`
 | 
			
		||||
	ServerAddress string `json:"serveraddress,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ~/.docker/config.json file info
 | 
			
		||||
type ConfigFile struct {
 | 
			
		||||
	AuthConfigs map[string]AuthConfig `json:"auths"`
 | 
			
		||||
	HttpHeaders map[string]string     `json:"HttpHeaders,omitempty"`
 | 
			
		||||
	filename    string                // Note: not serialized - for internal use only
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type RequestAuthorization struct {
 | 
			
		||||
	authConfig       *AuthConfig
 | 
			
		||||
	authConfig       *cliconfig.AuthConfig
 | 
			
		||||
	registryEndpoint *Endpoint
 | 
			
		||||
	resource         string
 | 
			
		||||
	scope            string
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +26,7 @@ type RequestAuthorization struct {
 | 
			
		|||
	tokenExpiration time.Time
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewRequestAuthorization(authConfig *AuthConfig, registryEndpoint *Endpoint, resource, scope string, actions []string) *RequestAuthorization {
 | 
			
		||||
func NewRequestAuthorization(authConfig *cliconfig.AuthConfig, registryEndpoint *Endpoint, resource, scope string, actions []string) *RequestAuthorization {
 | 
			
		||||
	return &RequestAuthorization{
 | 
			
		||||
		authConfig:       authConfig,
 | 
			
		||||
		registryEndpoint: registryEndpoint,
 | 
			
		||||
| 
						 | 
				
			
			@ -121,160 +91,8 @@ func (auth *RequestAuthorization) Authorize(req *http.Request) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// create a base64 encoded auth string to store in config
 | 
			
		||||
func encodeAuth(authConfig *AuthConfig) string {
 | 
			
		||||
	authStr := authConfig.Username + ":" + authConfig.Password
 | 
			
		||||
	msg := []byte(authStr)
 | 
			
		||||
	encoded := make([]byte, base64.StdEncoding.EncodedLen(len(msg)))
 | 
			
		||||
	base64.StdEncoding.Encode(encoded, msg)
 | 
			
		||||
	return string(encoded)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// decode the auth string
 | 
			
		||||
func decodeAuth(authStr string) (string, string, error) {
 | 
			
		||||
	decLen := base64.StdEncoding.DecodedLen(len(authStr))
 | 
			
		||||
	decoded := make([]byte, decLen)
 | 
			
		||||
	authByte := []byte(authStr)
 | 
			
		||||
	n, err := base64.StdEncoding.Decode(decoded, authByte)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", "", err
 | 
			
		||||
	}
 | 
			
		||||
	if n > decLen {
 | 
			
		||||
		return "", "", fmt.Errorf("Something went wrong decoding auth config")
 | 
			
		||||
	}
 | 
			
		||||
	arr := strings.SplitN(string(decoded), ":", 2)
 | 
			
		||||
	if len(arr) != 2 {
 | 
			
		||||
		return "", "", fmt.Errorf("Invalid auth configuration file")
 | 
			
		||||
	}
 | 
			
		||||
	password := strings.Trim(arr[1], "\x00")
 | 
			
		||||
	return arr[0], password, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// load up the auth config information and return values
 | 
			
		||||
// FIXME: use the internal golang config parser
 | 
			
		||||
func LoadConfig(configDir string) (*ConfigFile, error) {
 | 
			
		||||
	if configDir == "" {
 | 
			
		||||
		configDir = filepath.Join(homedir.Get(), ".docker")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	configFile := ConfigFile{
 | 
			
		||||
		AuthConfigs: make(map[string]AuthConfig),
 | 
			
		||||
		filename:    filepath.Join(configDir, CONFIGFILE),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Try happy path first - latest config file
 | 
			
		||||
	if _, err := os.Stat(configFile.filename); err == nil {
 | 
			
		||||
		file, err := os.Open(configFile.filename)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return &configFile, err
 | 
			
		||||
		}
 | 
			
		||||
		defer file.Close()
 | 
			
		||||
 | 
			
		||||
		if err := json.NewDecoder(file).Decode(&configFile); err != nil {
 | 
			
		||||
			return &configFile, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for addr, ac := range configFile.AuthConfigs {
 | 
			
		||||
			ac.Username, ac.Password, err = decodeAuth(ac.Auth)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return &configFile, err
 | 
			
		||||
			}
 | 
			
		||||
			ac.Auth = ""
 | 
			
		||||
			ac.ServerAddress = addr
 | 
			
		||||
			configFile.AuthConfigs[addr] = ac
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return &configFile, nil
 | 
			
		||||
	} else if !os.IsNotExist(err) {
 | 
			
		||||
		// if file is there but we can't stat it for any reason other
 | 
			
		||||
		// than it doesn't exist then stop
 | 
			
		||||
		return &configFile, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Can't find latest config file so check for the old one
 | 
			
		||||
	confFile := filepath.Join(homedir.Get(), OLD_CONFIGFILE)
 | 
			
		||||
 | 
			
		||||
	if _, err := os.Stat(confFile); err != nil {
 | 
			
		||||
		return &configFile, nil //missing file is not an error
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b, err := ioutil.ReadFile(confFile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return &configFile, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := json.Unmarshal(b, &configFile.AuthConfigs); err != nil {
 | 
			
		||||
		arr := strings.Split(string(b), "\n")
 | 
			
		||||
		if len(arr) < 2 {
 | 
			
		||||
			return &configFile, fmt.Errorf("The Auth config file is empty")
 | 
			
		||||
		}
 | 
			
		||||
		authConfig := AuthConfig{}
 | 
			
		||||
		origAuth := strings.Split(arr[0], " = ")
 | 
			
		||||
		if len(origAuth) != 2 {
 | 
			
		||||
			return &configFile, fmt.Errorf("Invalid Auth config file")
 | 
			
		||||
		}
 | 
			
		||||
		authConfig.Username, authConfig.Password, err = decodeAuth(origAuth[1])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return &configFile, err
 | 
			
		||||
		}
 | 
			
		||||
		origEmail := strings.Split(arr[1], " = ")
 | 
			
		||||
		if len(origEmail) != 2 {
 | 
			
		||||
			return &configFile, fmt.Errorf("Invalid Auth config file")
 | 
			
		||||
		}
 | 
			
		||||
		authConfig.Email = origEmail[1]
 | 
			
		||||
		authConfig.ServerAddress = IndexServerAddress()
 | 
			
		||||
		// *TODO: Switch to using IndexServerName() instead?
 | 
			
		||||
		configFile.AuthConfigs[IndexServerAddress()] = authConfig
 | 
			
		||||
	} else {
 | 
			
		||||
		for k, authConfig := range configFile.AuthConfigs {
 | 
			
		||||
			authConfig.Username, authConfig.Password, err = decodeAuth(authConfig.Auth)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return &configFile, err
 | 
			
		||||
			}
 | 
			
		||||
			authConfig.Auth = ""
 | 
			
		||||
			authConfig.ServerAddress = k
 | 
			
		||||
			configFile.AuthConfigs[k] = authConfig
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return &configFile, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (configFile *ConfigFile) Save() error {
 | 
			
		||||
	// Encode sensitive data into a new/temp struct
 | 
			
		||||
	tmpAuthConfigs := make(map[string]AuthConfig, len(configFile.AuthConfigs))
 | 
			
		||||
	for k, authConfig := range configFile.AuthConfigs {
 | 
			
		||||
		authCopy := authConfig
 | 
			
		||||
 | 
			
		||||
		authCopy.Auth = encodeAuth(&authCopy)
 | 
			
		||||
		authCopy.Username = ""
 | 
			
		||||
		authCopy.Password = ""
 | 
			
		||||
		authCopy.ServerAddress = ""
 | 
			
		||||
		tmpAuthConfigs[k] = authCopy
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	saveAuthConfigs := configFile.AuthConfigs
 | 
			
		||||
	configFile.AuthConfigs = tmpAuthConfigs
 | 
			
		||||
	defer func() { configFile.AuthConfigs = saveAuthConfigs }()
 | 
			
		||||
 | 
			
		||||
	data, err := json.MarshalIndent(configFile, "", "\t")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := os.MkdirAll(filepath.Dir(configFile.filename), 0700); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = ioutil.WriteFile(configFile.filename, data, 0600)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Login tries to register/login to the registry server.
 | 
			
		||||
func Login(authConfig *AuthConfig, registryEndpoint *Endpoint, factory *requestdecorator.RequestFactory) (string, error) {
 | 
			
		||||
func Login(authConfig *cliconfig.AuthConfig, registryEndpoint *Endpoint, factory *requestdecorator.RequestFactory) (string, error) {
 | 
			
		||||
	// Separates the v2 registry login logic from the v1 logic.
 | 
			
		||||
	if registryEndpoint.Version == APIVersion2 {
 | 
			
		||||
		return loginV2(authConfig, registryEndpoint, factory)
 | 
			
		||||
| 
						 | 
				
			
			@ -283,7 +101,7 @@ func Login(authConfig *AuthConfig, registryEndpoint *Endpoint, factory *requestd
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// loginV1 tries to register/login to the v1 registry server.
 | 
			
		||||
func loginV1(authConfig *AuthConfig, registryEndpoint *Endpoint, factory *requestdecorator.RequestFactory) (string, error) {
 | 
			
		||||
func loginV1(authConfig *cliconfig.AuthConfig, registryEndpoint *Endpoint, factory *requestdecorator.RequestFactory) (string, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		status        string
 | 
			
		||||
		reqBody       []byte
 | 
			
		||||
| 
						 | 
				
			
			@ -396,7 +214,7 @@ func loginV1(authConfig *AuthConfig, registryEndpoint *Endpoint, factory *reques
 | 
			
		|||
// now, users should create their account through other means like directly from a web page
 | 
			
		||||
// served by the v2 registry service provider. Whether this will be supported in the future
 | 
			
		||||
// is to be determined.
 | 
			
		||||
func loginV2(authConfig *AuthConfig, registryEndpoint *Endpoint, factory *requestdecorator.RequestFactory) (string, error) {
 | 
			
		||||
func loginV2(authConfig *cliconfig.AuthConfig, registryEndpoint *Endpoint, factory *requestdecorator.RequestFactory) (string, error) {
 | 
			
		||||
	logrus.Debugf("attempting v2 login to registry endpoint %s", registryEndpoint)
 | 
			
		||||
	var (
 | 
			
		||||
		err       error
 | 
			
		||||
| 
						 | 
				
			
			@ -429,7 +247,7 @@ func loginV2(authConfig *AuthConfig, registryEndpoint *Endpoint, factory *reques
 | 
			
		|||
	return "", fmt.Errorf("no successful auth challenge for %s - errors: %s", registryEndpoint, allErrors)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func tryV2BasicAuthLogin(authConfig *AuthConfig, params map[string]string, registryEndpoint *Endpoint, client *http.Client, factory *requestdecorator.RequestFactory) error {
 | 
			
		||||
func tryV2BasicAuthLogin(authConfig *cliconfig.AuthConfig, params map[string]string, registryEndpoint *Endpoint, client *http.Client, factory *requestdecorator.RequestFactory) error {
 | 
			
		||||
	req, err := factory.NewRequest("GET", registryEndpoint.Path(""), nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
| 
						 | 
				
			
			@ -450,7 +268,7 @@ func tryV2BasicAuthLogin(authConfig *AuthConfig, params map[string]string, regis
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func tryV2TokenAuthLogin(authConfig *AuthConfig, params map[string]string, registryEndpoint *Endpoint, client *http.Client, factory *requestdecorator.RequestFactory) error {
 | 
			
		||||
func tryV2TokenAuthLogin(authConfig *cliconfig.AuthConfig, params map[string]string, registryEndpoint *Endpoint, client *http.Client, factory *requestdecorator.RequestFactory) error {
 | 
			
		||||
	token, err := getToken(authConfig.Username, authConfig.Password, params, registryEndpoint, client, factory)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
| 
						 | 
				
			
			@ -477,7 +295,7 @@ func tryV2TokenAuthLogin(authConfig *AuthConfig, params map[string]string, regis
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// this method matches a auth configuration to a server address or a url
 | 
			
		||||
func (config *ConfigFile) ResolveAuthConfig(index *IndexInfo) AuthConfig {
 | 
			
		||||
func ResolveAuthConfig(config *cliconfig.ConfigFile, index *IndexInfo) cliconfig.AuthConfig {
 | 
			
		||||
	configKey := index.GetAuthConfigKey()
 | 
			
		||||
	// First try the happy case
 | 
			
		||||
	if c, found := config.AuthConfigs[configKey]; found || index.Official {
 | 
			
		||||
| 
						 | 
				
			
			@ -499,16 +317,12 @@ func (config *ConfigFile) ResolveAuthConfig(index *IndexInfo) AuthConfig {
 | 
			
		|||
 | 
			
		||||
	// Maybe they have a legacy config file, we will iterate the keys converting
 | 
			
		||||
	// them to the new format and testing
 | 
			
		||||
	for registry, config := range config.AuthConfigs {
 | 
			
		||||
	for registry, ac := range config.AuthConfigs {
 | 
			
		||||
		if configKey == convertToHostname(registry) {
 | 
			
		||||
			return config
 | 
			
		||||
			return ac
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// When all else fails, return an empty auth config
 | 
			
		||||
	return AuthConfig{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (config *ConfigFile) Filename() string {
 | 
			
		||||
	return config.filename
 | 
			
		||||
	return cliconfig.AuthConfig{}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,14 +5,16 @@ import (
 | 
			
		|||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestEncodeAuth(t *testing.T) {
 | 
			
		||||
	newAuthConfig := &AuthConfig{Username: "ken", Password: "test", Email: "test@example.com"}
 | 
			
		||||
	authStr := encodeAuth(newAuthConfig)
 | 
			
		||||
	decAuthConfig := &AuthConfig{}
 | 
			
		||||
	newAuthConfig := &cliconfig.AuthConfig{Username: "ken", Password: "test", Email: "test@example.com"}
 | 
			
		||||
	authStr := cliconfig.EncodeAuth(newAuthConfig)
 | 
			
		||||
	decAuthConfig := &cliconfig.AuthConfig{}
 | 
			
		||||
	var err error
 | 
			
		||||
	decAuthConfig.Username, decAuthConfig.Password, err = decodeAuth(authStr)
 | 
			
		||||
	decAuthConfig.Username, decAuthConfig.Password, err = cliconfig.DecodeAuth(authStr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -27,19 +29,16 @@ func TestEncodeAuth(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setupTempConfigFile() (*ConfigFile, error) {
 | 
			
		||||
func setupTempConfigFile() (*cliconfig.ConfigFile, error) {
 | 
			
		||||
	root, err := ioutil.TempDir("", "docker-test-auth")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	root = filepath.Join(root, CONFIGFILE)
 | 
			
		||||
	configFile := &ConfigFile{
 | 
			
		||||
		AuthConfigs: make(map[string]AuthConfig),
 | 
			
		||||
		filename:    root,
 | 
			
		||||
	}
 | 
			
		||||
	root = filepath.Join(root, cliconfig.CONFIGFILE)
 | 
			
		||||
	configFile := cliconfig.NewConfigFile(root)
 | 
			
		||||
 | 
			
		||||
	for _, registry := range []string{"testIndex", IndexServerAddress()} {
 | 
			
		||||
		configFile.AuthConfigs[registry] = AuthConfig{
 | 
			
		||||
		configFile.AuthConfigs[registry] = cliconfig.AuthConfig{
 | 
			
		||||
			Username: "docker-user",
 | 
			
		||||
			Password: "docker-pass",
 | 
			
		||||
			Email:    "docker@docker.io",
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +53,7 @@ func TestSameAuthDataPostSave(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer os.RemoveAll(configFile.filename)
 | 
			
		||||
	defer os.RemoveAll(configFile.Filename())
 | 
			
		||||
 | 
			
		||||
	err = configFile.Save()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -81,7 +80,7 @@ func TestResolveAuthConfigIndexServer(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer os.RemoveAll(configFile.filename)
 | 
			
		||||
	defer os.RemoveAll(configFile.Filename())
 | 
			
		||||
 | 
			
		||||
	indexConfig := configFile.AuthConfigs[IndexServerAddress()]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -92,10 +91,10 @@ func TestResolveAuthConfigIndexServer(t *testing.T) {
 | 
			
		|||
		Official: false,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resolved := configFile.ResolveAuthConfig(officialIndex)
 | 
			
		||||
	resolved := ResolveAuthConfig(configFile, officialIndex)
 | 
			
		||||
	assertEqual(t, resolved, indexConfig, "Expected ResolveAuthConfig to return IndexServerAddress()")
 | 
			
		||||
 | 
			
		||||
	resolved = configFile.ResolveAuthConfig(privateIndex)
 | 
			
		||||
	resolved = ResolveAuthConfig(configFile, privateIndex)
 | 
			
		||||
	assertNotEqual(t, resolved, indexConfig, "Expected ResolveAuthConfig to not return IndexServerAddress()")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -104,26 +103,26 @@ func TestResolveAuthConfigFullURL(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer os.RemoveAll(configFile.filename)
 | 
			
		||||
	defer os.RemoveAll(configFile.Filename())
 | 
			
		||||
 | 
			
		||||
	registryAuth := AuthConfig{
 | 
			
		||||
	registryAuth := cliconfig.AuthConfig{
 | 
			
		||||
		Username: "foo-user",
 | 
			
		||||
		Password: "foo-pass",
 | 
			
		||||
		Email:    "foo@example.com",
 | 
			
		||||
	}
 | 
			
		||||
	localAuth := AuthConfig{
 | 
			
		||||
	localAuth := cliconfig.AuthConfig{
 | 
			
		||||
		Username: "bar-user",
 | 
			
		||||
		Password: "bar-pass",
 | 
			
		||||
		Email:    "bar@example.com",
 | 
			
		||||
	}
 | 
			
		||||
	officialAuth := AuthConfig{
 | 
			
		||||
	officialAuth := cliconfig.AuthConfig{
 | 
			
		||||
		Username: "baz-user",
 | 
			
		||||
		Password: "baz-pass",
 | 
			
		||||
		Email:    "baz@example.com",
 | 
			
		||||
	}
 | 
			
		||||
	configFile.AuthConfigs[IndexServerAddress()] = officialAuth
 | 
			
		||||
 | 
			
		||||
	expectedAuths := map[string]AuthConfig{
 | 
			
		||||
	expectedAuths := map[string]cliconfig.AuthConfig{
 | 
			
		||||
		"registry.example.com": registryAuth,
 | 
			
		||||
		"localhost:8000":       localAuth,
 | 
			
		||||
		"registry.com":         localAuth,
 | 
			
		||||
| 
						 | 
				
			
			@ -160,12 +159,12 @@ func TestResolveAuthConfigFullURL(t *testing.T) {
 | 
			
		|||
		}
 | 
			
		||||
		for _, registry := range registries {
 | 
			
		||||
			configFile.AuthConfigs[registry] = configured
 | 
			
		||||
			resolved := configFile.ResolveAuthConfig(index)
 | 
			
		||||
			resolved := ResolveAuthConfig(configFile, index)
 | 
			
		||||
			if resolved.Email != configured.Email {
 | 
			
		||||
				t.Errorf("%s -> %q != %q\n", registry, resolved.Email, configured.Email)
 | 
			
		||||
			}
 | 
			
		||||
			delete(configFile.AuthConfigs, registry)
 | 
			
		||||
			resolved = configFile.ResolveAuthConfig(index)
 | 
			
		||||
			resolved = ResolveAuthConfig(configFile, index)
 | 
			
		||||
			if resolved.Email == configured.Email {
 | 
			
		||||
				t.Errorf("%s -> %q == %q\n", registry, resolved.Email, configured.Email)
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	"github.com/docker/docker/pkg/requestdecorator"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +21,7 @@ const (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
func spawnTestRegistrySession(t *testing.T) *Session {
 | 
			
		||||
	authConfig := &AuthConfig{}
 | 
			
		||||
	authConfig := &cliconfig.AuthConfig{}
 | 
			
		||||
	endpoint, err := NewEndpoint(makeIndex("/v1/"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +34,7 @@ func spawnTestRegistrySession(t *testing.T) *Session {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func TestPublicSession(t *testing.T) {
 | 
			
		||||
	authConfig := &AuthConfig{}
 | 
			
		||||
	authConfig := &cliconfig.AuthConfig{}
 | 
			
		||||
 | 
			
		||||
	getSessionDecorators := func(index *IndexInfo) int {
 | 
			
		||||
		endpoint, err := NewEndpoint(index)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
package registry
 | 
			
		||||
 | 
			
		||||
import "github.com/docker/docker/cliconfig"
 | 
			
		||||
 | 
			
		||||
type Service struct {
 | 
			
		||||
	Config *ServiceConfig
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +17,7 @@ func NewService(options *Options) *Service {
 | 
			
		|||
// Auth contacts the public registry with the provided credentials,
 | 
			
		||||
// and returns OK if authentication was sucessful.
 | 
			
		||||
// It can be used to verify the validity of a client's credentials.
 | 
			
		||||
func (s *Service) Auth(authConfig *AuthConfig) (string, error) {
 | 
			
		||||
func (s *Service) Auth(authConfig *cliconfig.AuthConfig) (string, error) {
 | 
			
		||||
	addr := authConfig.ServerAddress
 | 
			
		||||
	if addr == "" {
 | 
			
		||||
		// Use the official registry address if not specified.
 | 
			
		||||
| 
						 | 
				
			
			@ -35,7 +37,7 @@ func (s *Service) Auth(authConfig *AuthConfig) (string, error) {
 | 
			
		|||
 | 
			
		||||
// Search queries the public registry for images matching the specified
 | 
			
		||||
// search terms, and returns the results.
 | 
			
		||||
func (s *Service) Search(term string, authConfig *AuthConfig, headers map[string][]string) (*SearchResults, error) {
 | 
			
		||||
func (s *Service) Search(term string, authConfig *cliconfig.AuthConfig, headers map[string][]string) (*SearchResults, error) {
 | 
			
		||||
	repoInfo, err := s.ResolveRepository(term)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,20 +18,21 @@ import (
 | 
			
		|||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	"github.com/docker/docker/pkg/httputils"
 | 
			
		||||
	"github.com/docker/docker/pkg/requestdecorator"
 | 
			
		||||
	"github.com/docker/docker/pkg/tarsum"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Session struct {
 | 
			
		||||
	authConfig    *AuthConfig
 | 
			
		||||
	authConfig    *cliconfig.AuthConfig
 | 
			
		||||
	reqFactory    *requestdecorator.RequestFactory
 | 
			
		||||
	indexEndpoint *Endpoint
 | 
			
		||||
	jar           *cookiejar.Jar
 | 
			
		||||
	timeout       TimeoutType
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewSession(authConfig *AuthConfig, factory *requestdecorator.RequestFactory, endpoint *Endpoint, timeout bool) (r *Session, err error) {
 | 
			
		||||
func NewSession(authConfig *cliconfig.AuthConfig, factory *requestdecorator.RequestFactory, endpoint *Endpoint, timeout bool) (r *Session, err error) {
 | 
			
		||||
	r = &Session{
 | 
			
		||||
		authConfig:    authConfig,
 | 
			
		||||
		indexEndpoint: endpoint,
 | 
			
		||||
| 
						 | 
				
			
			@ -600,12 +601,12 @@ func (r *Session) SearchRepositories(term string) (*SearchResults, error) {
 | 
			
		|||
	return result, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Session) GetAuthConfig(withPasswd bool) *AuthConfig {
 | 
			
		||||
func (r *Session) GetAuthConfig(withPasswd bool) *cliconfig.AuthConfig {
 | 
			
		||||
	password := ""
 | 
			
		||||
	if withPasswd {
 | 
			
		||||
		password = r.authConfig.Password
 | 
			
		||||
	}
 | 
			
		||||
	return &AuthConfig{
 | 
			
		||||
	return &cliconfig.AuthConfig{
 | 
			
		||||
		Username: r.authConfig.Username,
 | 
			
		||||
		Password: password,
 | 
			
		||||
		Email:    r.authConfig.Email,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue