Remove email address field from login

This removes the email prompt when you use docker login, and also removes the ability to register via the docker cli. Docker login, will strictly be used for logging into a registry server.

Signed-off-by: Ken Cochrane <kencochrane@gmail.com>
This commit is contained in:
Ken Cochrane 2016-02-29 17:51:36 -08:00 committed by Derek McGowan
parent 6a96006959
commit aee260d4eb
18 changed files with 180 additions and 182 deletions

View File

@ -17,7 +17,7 @@ import (
"github.com/docker/engine-api/types"
)
// CmdLogin logs in or registers a user to a Docker registry service.
// CmdLogin logs in a user to a Docker registry service.
//
// If no server is specified, the user will be logged into or registered to the registry's index server.
//
@ -28,7 +28,9 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
flUser := cmd.String([]string{"u", "-username"}, "", "Username")
flPassword := cmd.String([]string{"p", "-password"}, "", "Password")
flEmail := cmd.String([]string{"e", "-email"}, "", "Email")
// Deprecated in 1.11: Should be removed in docker 1.13
cmd.String([]string{"#e", "#-email"}, "", "Email")
cmd.ParseFlags(args, true)
@ -38,13 +40,15 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
}
var serverAddress string
var isDefaultRegistry bool
if len(cmd.Args()) > 0 {
serverAddress = cmd.Arg(0)
} else {
serverAddress = cli.electAuthServer()
isDefaultRegistry = true
}
authConfig, err := cli.configureAuth(*flUser, *flPassword, *flEmail, serverAddress)
authConfig, err := cli.configureAuth(*flUser, *flPassword, serverAddress, isDefaultRegistry)
if err != nil {
return err
}
@ -77,7 +81,7 @@ func (cli *DockerCli) promptWithDefault(prompt string, configDefault string) {
}
}
func (cli *DockerCli) configureAuth(flUser, flPassword, flEmail, serverAddress string) (types.AuthConfig, error) {
func (cli *DockerCli) configureAuth(flUser, flPassword, serverAddress string, isDefaultRegistry bool) (types.AuthConfig, error) {
authconfig, err := getCredentials(cli.configFile, serverAddress)
if err != nil {
return authconfig, err
@ -86,6 +90,10 @@ func (cli *DockerCli) configureAuth(flUser, flPassword, flEmail, serverAddress s
authconfig.Username = strings.TrimSpace(authconfig.Username)
if flUser = strings.TrimSpace(flUser); flUser == "" {
if isDefaultRegistry {
// if this is a defauly registry (docker hub), then display the following message.
fmt.Fprintln(cli.out, "Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.")
}
cli.promptWithDefault("Username", authconfig.Username)
flUser = readInput(cli.in, cli.out)
flUser = strings.TrimSpace(flUser)
@ -115,29 +123,8 @@ func (cli *DockerCli) configureAuth(flUser, flPassword, flEmail, serverAddress s
}
}
// Assume that a different username means they may not want to use
// the email from the config file, so prompt it
if flUser != authconfig.Username {
if flEmail == "" {
cli.promptWithDefault("Email", authconfig.Email)
flEmail = readInput(cli.in, cli.out)
if flEmail == "" {
flEmail = authconfig.Email
}
}
} else {
// However, if they don't override the username use the
// email from the cmd line if specified. IOW, allow
// then to change/override them. And if not specified, just
// use what's in the config file
if flEmail == "" {
flEmail = authconfig.Email
}
}
authconfig.Username = flUser
authconfig.Password = flPassword
authconfig.Email = flEmail
authconfig.ServerAddress = serverAddress
return authconfig, nil

View File

@ -48,7 +48,7 @@ func (cli *DockerCli) registryAuthenticationPrivilegedFunc(index *registrytypes.
return func() (string, error) {
fmt.Fprintf(cli.out, "\nPlease login prior to %s:\n", cmdName)
indexServer := registry.GetAuthConfigKey(index)
authConfig, err := cli.configureAuth("", "", "", indexServer)
authConfig, err := cli.configureAuth("", "", indexServer, false)
if err != nil {
return "", err
}

View File

@ -88,11 +88,6 @@ func (configFile *ConfigFile) LegacyLoadFromReader(configData io.Reader) error {
if err != nil {
return err
}
origEmail := strings.Split(arr[1], " = ")
if len(origEmail) != 2 {
return fmt.Errorf("Invalid Auth config file")
}
authConfig.Email = origEmail[1]
authConfig.ServerAddress = defaultIndexserver
configFile.AuthConfigs[defaultIndexserver] = authConfig
} else {

View File

@ -111,12 +111,9 @@ func TestOldInvalidsAuth(t *testing.T) {
invalids := map[string]string{
`username = test`: "The Auth config file is empty",
`username
password
email`: "Invalid Auth config file",
password`: "Invalid Auth config file",
`username = test
email`: "Invalid auth configuration file",
`username = am9lam9lOmhlbGxv
email`: "Invalid Auth config file",
}
tmpHome, err := ioutil.TempDir("", "config-test")
@ -164,7 +161,7 @@ func TestOldValidAuth(t *testing.T) {
fn := filepath.Join(tmpHome, oldConfigfile)
js := `username = am9lam9lOmhlbGxv
email = user@example.com`
email = user@example.com`
if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
t.Fatal(err)
}
@ -176,15 +173,23 @@ email = user@example.com`
// defaultIndexserver is https://index.docker.io/v1/
ac := config.AuthConfigs["https://index.docker.io/v1/"]
if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
if ac.Username != "joejoe" || ac.Password != "hello" {
t.Fatalf("Missing data from parsing:\n%q", config)
}
// Now save it and make sure it shows up in new form
configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)
if !strings.Contains(configStr, "user@example.com") {
t.Fatalf("Should have save in new form: %s", configStr)
expConfStr := `{
"auths": {
"https://index.docker.io/v1/": {
"auth": "am9lam9lOmhlbGxv"
}
}
}`
if configStr != expConfStr {
t.Fatalf("Should have save in new form: \n%s\n not \n%s", configStr, expConfStr)
}
}
@ -239,15 +244,24 @@ func TestOldJson(t *testing.T) {
}
ac := config.AuthConfigs["https://index.docker.io/v1/"]
if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
if ac.Username != "joejoe" || ac.Password != "hello" {
t.Fatalf("Missing data from parsing:\n%q", config)
}
// Now save it and make sure it shows up in new form
configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)
if !strings.Contains(configStr, "user@example.com") {
t.Fatalf("Should have save in new form: %s", configStr)
expConfStr := `{
"auths": {
"https://index.docker.io/v1/": {
"auth": "am9lam9lOmhlbGxv",
"email": "user@example.com"
}
}
}`
if configStr != expConfStr {
t.Fatalf("Should have save in new form: \n'%s'\n not \n'%s'\n", configStr, expConfStr)
}
}
@ -259,7 +273,7 @@ func TestNewJson(t *testing.T) {
defer os.RemoveAll(tmpHome)
fn := filepath.Join(tmpHome, ConfigFileName)
js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } } }`
js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv" } } }`
if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
t.Fatal(err)
}
@ -270,15 +284,62 @@ func TestNewJson(t *testing.T) {
}
ac := config.AuthConfigs["https://index.docker.io/v1/"]
if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
if ac.Username != "joejoe" || ac.Password != "hello" {
t.Fatalf("Missing data from parsing:\n%q", config)
}
// Now save it and make sure it shows up in new form
configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)
if !strings.Contains(configStr, "user@example.com") {
t.Fatalf("Should have save in new form: %s", configStr)
expConfStr := `{
"auths": {
"https://index.docker.io/v1/": {
"auth": "am9lam9lOmhlbGxv"
}
}
}`
if configStr != expConfStr {
t.Fatalf("Should have save in new form: \n%s\n not \n%s", configStr, expConfStr)
}
}
func TestNewJsonNoEmail(t *testing.T) {
tmpHome, err := ioutil.TempDir("", "config-test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpHome)
fn := filepath.Join(tmpHome, ConfigFileName)
js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv" } } }`
if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
t.Fatal(err)
}
config, err := Load(tmpHome)
if err != nil {
t.Fatalf("Failed loading on empty json file: %q", err)
}
ac := config.AuthConfigs["https://index.docker.io/v1/"]
if ac.Username != "joejoe" || ac.Password != "hello" {
t.Fatalf("Missing data from parsing:\n%q", config)
}
// Now save it and make sure it shows up in new form
configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)
expConfStr := `{
"auths": {
"https://index.docker.io/v1/": {
"auth": "am9lam9lOmhlbGxv"
}
}
}`
if configStr != expConfStr {
t.Fatalf("Should have save in new form: \n%s\n not \n%s", configStr, expConfStr)
}
}
@ -366,7 +427,7 @@ func TestJsonReaderNoFile(t *testing.T) {
}
ac := config.AuthConfigs["https://index.docker.io/v1/"]
if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
if ac.Username != "joejoe" || ac.Password != "hello" {
t.Fatalf("Missing data from parsing:\n%q", config)
}
@ -381,7 +442,7 @@ func TestOldJsonReaderNoFile(t *testing.T) {
}
ac := config.AuthConfigs["https://index.docker.io/v1/"]
if ac.Email != "user@example.com" || ac.Username != "joejoe" || ac.Password != "hello" {
if ac.Username != "joejoe" || ac.Password != "hello" {
t.Fatalf("Missing data from parsing:\n%q", config)
}
}
@ -404,7 +465,7 @@ func TestJsonWithPsFormatNoFile(t *testing.T) {
func TestJsonSaveWithNoFile(t *testing.T) {
js := `{
"auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } },
"auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv" } },
"psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}"
}`
config, err := LoadFromReader(strings.NewReader(js))
@ -426,9 +487,16 @@ func TestJsonSaveWithNoFile(t *testing.T) {
t.Fatalf("Failed saving to file: %q", err)
}
buf, err := ioutil.ReadFile(filepath.Join(tmpHome, ConfigFileName))
if !strings.Contains(string(buf), `"auths":`) ||
!strings.Contains(string(buf), "user@example.com") {
t.Fatalf("Should have save in new form: %s", string(buf))
expConfStr := `{
"auths": {
"https://index.docker.io/v1/": {
"auth": "am9lam9lOmhlbGxv"
}
},
"psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}"
}`
if string(buf) != expConfStr {
t.Fatalf("Should have save in new form: \n%s\nnot \n%s", string(buf), expConfStr)
}
}
@ -454,14 +522,23 @@ func TestLegacyJsonSaveWithNoFile(t *testing.T) {
t.Fatalf("Failed saving to file: %q", err)
}
buf, err := ioutil.ReadFile(filepath.Join(tmpHome, ConfigFileName))
if !strings.Contains(string(buf), `"auths":`) ||
!strings.Contains(string(buf), "user@example.com") {
t.Fatalf("Should have save in new form: %s", string(buf))
expConfStr := `{
"auths": {
"https://index.docker.io/v1/": {
"auth": "am9lam9lOmhlbGxv",
"email": "user@example.com"
}
}
}`
if string(buf) != expConfStr {
t.Fatalf("Should have save in new form: \n%s\n not \n%s", string(buf), expConfStr)
}
}
func TestEncodeAuth(t *testing.T) {
newAuthConfig := &types.AuthConfig{Username: "ken", Password: "test", Email: "test@example.com"}
newAuthConfig := &types.AuthConfig{Username: "ken", Password: "test"}
authStr := encodeAuth(newAuthConfig)
decAuthConfig := &types.AuthConfig{}
var err error

View File

@ -811,7 +811,7 @@ _docker_daemon() {
return
;;
esac
local key=$(__docker_map_key_of_current_option '--storage-opt')
case "$key" in
dm.@(blkdiscard|override_udev_sync_check|use_deferred_@(removal|deletion)))
@ -1205,14 +1205,14 @@ _docker_load() {
_docker_login() {
case "$prev" in
--email|-e|--password|-p|--username|-u)
--password|-p|--username|-u)
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--email -e --help --password -p --username -u" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--help --password -p --username -u" -- "$cur" ) )
;;
esac
}

View File

@ -221,8 +221,7 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from load' -l help -d 'Print
complete -c docker -A -f -n '__fish_seen_subcommand_from load' -s i -l input -d 'Read from a tar archive file, instead of STDIN'
# login
complete -c docker -f -n '__fish_docker_no_subcommand' -a login -d 'Register or log in to a Docker registry server'
complete -c docker -A -f -n '__fish_seen_subcommand_from login' -s e -l email -d 'Email'
complete -c docker -f -n '__fish_docker_no_subcommand' -a login -d 'Log in to a Docker registry server'
complete -c docker -A -f -n '__fish_seen_subcommand_from login' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from login' -s p -l password -d 'Password'
complete -c docker -A -f -n '__fish_seen_subcommand_from login' -s u -l username -d 'Username'
@ -399,5 +398,3 @@ complete -c docker -f -n '__fish_docker_no_subcommand' -a version -d 'Show the D
complete -c docker -f -n '__fish_docker_no_subcommand' -a wait -d 'Block until a container stops, then print its exit code'
complete -c docker -A -f -n '__fish_seen_subcommand_from wait' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from wait' -a '(__fish_print_docker_containers running)' -d "Container"

View File

@ -812,7 +812,6 @@ __docker_subcommand() {
(login)
_arguments $(__docker_arguments) \
$opts_help \
"($help -e --email)"{-e=,--email=}"[Email]:email: " \
"($help -p --password)"{-p=,--password=}"[Password]:password: " \
"($help -u --user)"{-u=,--user=}"[Username]:username: " \
"($help -)1:server: " && ret=0

View File

@ -14,6 +14,13 @@ weight=80
The following list of features are deprecated in Engine.
### `-e` and `--email` flags on `docker login`
**Deprecated In Release: v1.11**
**Target For Removal In Release: v1.13**
The docker login command is removing the ability to automatically register for an account with the target registry if the given username doesn't exist. Due to this change, the email flag is no longer required, and will be deprecated.
### Ambiguous event fields in API
**Deprecated In Release: v1.10**

View File

@ -12,10 +12,9 @@ parent = "smn_cli"
Usage: docker login [OPTIONS] [SERVER]
Register or log in to a Docker registry server, if no server is
Log in to a Docker registry server, if no server is
specified "https://index.docker.io/v1/" is the default.
-e, --email="" Email
--help Print usage
-p, --password="" Password
-u, --username="" Username
@ -27,10 +26,10 @@ adding the server name.
$ docker login localhost:8080
`docker login` requires user to use `sudo` or be `root`, except when:
`docker login` requires user to use `sudo` or be `root`, except when:
1. connecting to a remote daemon, such as a `docker-machine` provisioned `docker engine`.
2. user is added to the `docker` group. This will impact the security of your system; the `docker` group is `root` equivalent. See [Docker Daemon Attack Surface](https://docs.docker.com/security/security/#docker-daemon-attack-surface) for details.
2. user is added to the `docker` group. This will impact the security of your system; the `docker` group is `root` equivalent. See [Docker Daemon Attack Surface](https://docs.docker.com/security/security/#docker-daemon-attack-surface) for details.
You can log into any public or private repository for which you have
credentials. When you log in, the command stores encoded credentials in

View File

@ -33,15 +33,11 @@ Docker itself provides access to Docker Hub services via the `docker search`,
### Account creation and login
Typically, you'll want to start by creating an account on Docker Hub (if you haven't
already) and logging in. You can create your account directly on
[Docker Hub](https://hub.docker.com/account/signup/), or by running:
[Docker Hub](https://hub.docker.com/account/signup/).
$ docker login
This will prompt you for a user name, which will become the public namespace for your
public repositories.
If your user name is available, Docker will prompt you to enter a password and your
e-mail address. It will then automatically log you in. You can now commit and
push your own images up to your repos on Docker Hub.
You can now commit and push your own images up to your repos on Docker Hub.
> **Note:**
> Your authentication credentials will be stored in the `~/.docker/config.json`

View File

@ -6548,7 +6548,7 @@ func (s *DockerSuite) TestBuildWorkdirWindowsPath(c *check.C) {
}
func (s *DockerRegistryAuthSuite) TestBuildFromAuthenticatedRegistry(c *check.C) {
dockerCmd(c, "login", "-u", s.reg.username, "-p", s.reg.password, "-e", s.reg.email, privateRegistryURL)
dockerCmd(c, "login", "-u", s.reg.username, "-p", s.reg.password, privateRegistryURL)
baseImage := privateRegistryURL + "/baseimage"

View File

@ -20,11 +20,25 @@ func (s *DockerSuite) TestLoginWithoutTTY(c *check.C) {
}
func (s *DockerRegistryAuthSuite) TestLoginToPrivateRegistry(c *check.C) {
// wrong credentials
out, _, err := dockerCmdWithError("login", "-u", s.reg.username, "-p", "WRONGPASSWORD", privateRegistryURL)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "401 Unauthorized")
// now it's fine
dockerCmd(c, "login", "-u", s.reg.username, "-p", s.reg.password, privateRegistryURL)
}
func (s *DockerRegistryAuthSuite) TestLoginToPrivateRegistryDeprecatedEmailFlag(c *check.C) {
// Test to make sure login still works with the deprecated -e and --email flags
// wrong credentials
out, _, err := dockerCmdWithError("login", "-u", s.reg.username, "-p", "WRONGPASSWORD", "-e", s.reg.email, privateRegistryURL)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "401 Unauthorized")
// now it's fine
// -e flag
dockerCmd(c, "login", "-u", s.reg.username, "-p", s.reg.password, "-e", s.reg.email, privateRegistryURL)
// --email flag
dockerCmd(c, "login", "-u", s.reg.username, "-p", s.reg.password, "--email", s.reg.email, privateRegistryURL)
}

View File

@ -390,7 +390,6 @@ func (s *DockerRegistryAuthSuite) TestPullWithExternalAuth(c *check.C) {
b, err := ioutil.ReadFile(configPath)
c.Assert(err, checker.IsNil)
c.Assert(string(b), checker.Not(checker.Contains), "\"auth\":")
c.Assert(string(b), checker.Contains, "email")
dockerCmd(c, "--config", tmp, "tag", "busybox", repoName)
dockerCmd(c, "--config", tmp, "push", repoName)

View File

@ -112,7 +112,7 @@ func (s *DockerRegistrySuite) TestV1(c *check.C) {
s.d.Cmd("run", repoName)
c.Assert(v1Repo, check.Not(check.Equals), 1, check.Commentf("Expected v1 repository access after run"))
s.d.Cmd("login", "-u", "richard", "-p", "testtest", "-e", "testuser@testdomain.com", reg.hostport)
s.d.Cmd("login", "-u", "richard", "-p", "testtest", reg.hostport)
c.Assert(v1Logins, check.Not(check.Equals), 0, check.Commentf("Expected v1 login attempt"))
s.d.Cmd("tag", "busybox", repoName)

View File

@ -2,26 +2,25 @@
% Docker Community
% JUNE 2014
# NAME
docker-login - Register or log in to a Docker registry.
docker-login - Log in to a Docker registry.
# SYNOPSIS
**docker login**
[**-e**|**--email**[=*EMAIL*]]
[**--help**]
[**-p**|**--password**[=*PASSWORD*]]
[**-u**|**--username**[=*USERNAME*]]
[SERVER]
# DESCRIPTION
Register or log in to a Docker Registry located on the specified
Log in to a Docker Registry located on the specified
`SERVER`. You can specify a URL or a `hostname` for the `SERVER` value. If you
do not specify a `SERVER`, the command uses Docker's public registry located at
`https://registry-1.docker.io/` by default. To get a username/password for Docker's public registry, create an account on Docker Hub.
`docker login` requires user to use `sudo` or be `root`, except when:
`docker login` requires user to use `sudo` or be `root`, except when:
1. connecting to a remote daemon, such as a `docker-machine` provisioned `docker engine`.
2. user is added to the `docker` group. This will impact the security of your system; the `docker` group is `root` equivalent. See [Docker Daemon Attack Surface](https://docs.docker.com/articles/security/#docker-daemon-attack-surface) for details.
2. user is added to the `docker` group. This will impact the security of your system; the `docker` group is `root` equivalent. See [Docker Daemon Attack Surface](https://docs.docker.com/articles/security/#docker-daemon-attack-surface) for details.
You can log into any public or private repository for which you have
credentials. When you log in, the command stores encoded credentials in
@ -31,9 +30,6 @@ credentials. When you log in, the command stores encoded credentials in
>
# OPTIONS
**-e**, **--email**=""
Email
**--help**
Print usage statement

View File

@ -1,7 +1,6 @@
package registry
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
@ -24,11 +23,8 @@ func Login(authConfig *types.AuthConfig, registryEndpoint *Endpoint) (string, er
// loginV1 tries to register/login to the v1 registry server.
func loginV1(authConfig *types.AuthConfig, registryEndpoint *Endpoint) (string, error) {
var (
status string
respBody []byte
err error
respStatusCode = 0
serverAddress = authConfig.ServerAddress
err error
serverAddress = authConfig.ServerAddress
)
logrus.Debugf("attempting v1 login to registry endpoint %s", registryEndpoint)
@ -39,93 +35,37 @@ func loginV1(authConfig *types.AuthConfig, registryEndpoint *Endpoint) (string,
loginAgainstOfficialIndex := serverAddress == IndexServer
// to avoid sending the server address to the server it should be removed before being marshaled
authCopy := *authConfig
authCopy.ServerAddress = ""
jsonBody, err := json.Marshal(authCopy)
req, err := http.NewRequest("GET", serverAddress+"users/", nil)
req.SetBasicAuth(authConfig.Username, authConfig.Password)
resp, err := registryEndpoint.client.Do(req)
if err != nil {
return "", fmt.Errorf("Config Error: %s", err)
return "", err
}
// using `bytes.NewReader(jsonBody)` here causes the server to respond with a 411 status.
b := strings.NewReader(string(jsonBody))
resp1, err := registryEndpoint.client.Post(serverAddress+"users/", "application/json; charset=utf-8", b)
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("Server Error: %s", err)
return "", err
}
defer resp1.Body.Close()
respStatusCode = resp1.StatusCode
respBody, err = ioutil.ReadAll(resp1.Body)
if err != nil {
return "", fmt.Errorf("Server Error: [%#v] %s", respStatusCode, err)
}
if respStatusCode == 201 {
if resp.StatusCode == http.StatusOK {
return "Login Succeeded", nil
} else if resp.StatusCode == http.StatusUnauthorized {
if loginAgainstOfficialIndex {
status = "Account created. Please use the confirmation link we sent" +
" to your e-mail to activate it."
} else {
// *TODO: Use registry configuration to determine what this says, if anything?
status = "Account created. Please see the documentation of the registry " + serverAddress + " for instructions how to activate it."
return "", fmt.Errorf("Wrong login/password, please try again. Haven't got a Docker ID? Create one at https://hub.docker.com")
}
} else if respStatusCode == 400 {
if string(respBody) == "\"Username or email already exists\"" {
req, err := http.NewRequest("GET", serverAddress+"users/", nil)
req.SetBasicAuth(authConfig.Username, authConfig.Password)
resp, err := registryEndpoint.client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
if resp.StatusCode == 200 {
return "Login Succeeded", nil
} else if resp.StatusCode == 401 {
return "", fmt.Errorf("Wrong login/password, please try again")
} else if resp.StatusCode == 403 {
if loginAgainstOfficialIndex {
return "", fmt.Errorf("Login: Account is not Active. Please check your e-mail for a confirmation link.")
}
// *TODO: Use registry configuration to determine what this says, if anything?
return "", fmt.Errorf("Login: Account is not Active. Please see the documentation of the registry %s for instructions how to activate it.", serverAddress)
} else if resp.StatusCode == 500 { // Issue #14326
logrus.Errorf("%s returned status code %d. Response Body :\n%s", req.URL.String(), resp.StatusCode, body)
return "", fmt.Errorf("Internal Server Error")
}
return "", fmt.Errorf("Login: %s (Code: %d; Headers: %s)", body, resp.StatusCode, resp.Header)
}
return "", fmt.Errorf("Registration: %s", respBody)
} else if respStatusCode == 401 {
// This case would happen with private registries where /v1/users is
// protected, so people can use `docker login` as an auth check.
req, err := http.NewRequest("GET", serverAddress+"users/", nil)
req.SetBasicAuth(authConfig.Username, authConfig.Password)
resp, err := registryEndpoint.client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
if resp.StatusCode == 200 {
return "Login Succeeded", nil
} else if resp.StatusCode == 401 {
return "", fmt.Errorf("Wrong login/password, please try again")
} else {
return "", fmt.Errorf("Login: %s (Code: %d; Headers: %s)", body,
resp.StatusCode, resp.Header)
return "", fmt.Errorf("Wrong login/password, please try again")
} else if resp.StatusCode == http.StatusForbidden {
if loginAgainstOfficialIndex {
return "", fmt.Errorf("Login: Account is not active. Please check your e-mail for a confirmation link.")
}
// *TODO: Use registry configuration to determine what this says, if anything?
return "", fmt.Errorf("Login: Account is not active. Please see the documentation of the registry %s for instructions how to activate it.", serverAddress)
} else if resp.StatusCode == http.StatusInternalServerError { // Issue #14326
logrus.Errorf("%s returned status code %d. Response Body :\n%s", req.URL.String(), resp.StatusCode, body)
return "", fmt.Errorf("Internal Server Error")
} else {
return "", fmt.Errorf("Unexpected status code [%d] : %s", respStatusCode, respBody)
return "", fmt.Errorf("Login: %s (Code: %d; Headers: %s)", body,
resp.StatusCode, resp.Header)
}
return status, nil
}
// loginV2 tries to login to the v2 registry server. The given registry endpoint has been

View File

@ -14,7 +14,6 @@ func buildAuthConfigs() map[string]types.AuthConfig {
authConfigs[registry] = types.AuthConfig{
Username: "docker-user",
Password: "docker-pass",
Email: "docker@docker.io",
}
}
@ -30,9 +29,6 @@ func TestSameAuthDataPostSave(t *testing.T) {
if authConfig.Password != "docker-pass" {
t.Fail()
}
if authConfig.Email != "docker@docker.io" {
t.Fail()
}
if authConfig.Auth != "" {
t.Fail()
}
@ -62,17 +58,14 @@ func TestResolveAuthConfigFullURL(t *testing.T) {
registryAuth := types.AuthConfig{
Username: "foo-user",
Password: "foo-pass",
Email: "foo@example.com",
}
localAuth := types.AuthConfig{
Username: "bar-user",
Password: "bar-pass",
Email: "bar@example.com",
}
officialAuth := types.AuthConfig{
Username: "baz-user",
Password: "baz-pass",
Email: "baz@example.com",
}
authConfigs[IndexServer] = officialAuth
@ -105,7 +98,7 @@ func TestResolveAuthConfigFullURL(t *testing.T) {
for configKey, registries := range validRegistries {
configured, ok := expectedAuths[configKey]
if !ok || configured.Email == "" {
if !ok {
t.Fail()
}
index := &registrytypes.IndexInfo{
@ -114,13 +107,13 @@ func TestResolveAuthConfigFullURL(t *testing.T) {
for _, registry := range registries {
authConfigs[registry] = configured
resolved := ResolveAuthConfig(authConfigs, index)
if resolved.Email != configured.Email {
t.Errorf("%s -> %q != %q\n", registry, resolved.Email, configured.Email)
if resolved.Username != configured.Username || resolved.Password != configured.Password {
t.Errorf("%s -> %v != %v\n", registry, resolved, configured)
}
delete(authConfigs, registry)
resolved = ResolveAuthConfig(authConfigs, index)
if resolved.Email == configured.Email {
t.Errorf("%s -> %q == %q\n", registry, resolved.Email, configured.Email)
if resolved.Username == configured.Username || resolved.Password == configured.Password {
t.Errorf("%s -> %v == %v\n", registry, resolved, configured)
}
}
}

View File

@ -752,7 +752,6 @@ func (r *Session) GetAuthConfig(withPasswd bool) *types.AuthConfig {
return &types.AuthConfig{
Username: r.authConfig.Username,
Password: password,
Email: r.authConfig.Email,
}
}