63af81b883
When requesting a token, the basic auth header is always being set even if there is no username value. This patch corrects this and does not set the basic auth header if the username is empty. Also fixes an issue where pulling all tags from a v2 registry succeeds when the image does not actually exist on the registry. Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)
84 lines
1.8 KiB
Go
84 lines
1.8 KiB
Go
package registry
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"github.com/docker/docker/utils"
|
|
)
|
|
|
|
type tokenResponse struct {
|
|
Token string `json:"token"`
|
|
}
|
|
|
|
func getToken(username, password string, params map[string]string, registryEndpoint *Endpoint, client *http.Client, factory *utils.HTTPRequestFactory) (token string, err error) {
|
|
realm, ok := params["realm"]
|
|
if !ok {
|
|
return "", errors.New("no realm specified for token auth challenge")
|
|
}
|
|
|
|
realmURL, err := url.Parse(realm)
|
|
if err != nil {
|
|
return "", fmt.Errorf("invalid token auth challenge realm: %s", err)
|
|
}
|
|
|
|
if realmURL.Scheme == "" {
|
|
if registryEndpoint.IsSecure {
|
|
realmURL.Scheme = "https"
|
|
} else {
|
|
realmURL.Scheme = "http"
|
|
}
|
|
}
|
|
|
|
req, err := factory.NewRequest("GET", realmURL.String(), nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
reqParams := req.URL.Query()
|
|
service := params["service"]
|
|
scope := params["scope"]
|
|
|
|
if service != "" {
|
|
reqParams.Add("service", service)
|
|
}
|
|
|
|
for _, scopeField := range strings.Fields(scope) {
|
|
reqParams.Add("scope", scopeField)
|
|
}
|
|
|
|
if username != "" {
|
|
reqParams.Add("account", username)
|
|
req.SetBasicAuth(username, password)
|
|
}
|
|
|
|
req.URL.RawQuery = reqParams.Encode()
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return "", fmt.Errorf("token auth attempt for registry %s: %s request failed with status: %d %s", registryEndpoint, req.URL, resp.StatusCode, http.StatusText(resp.StatusCode))
|
|
}
|
|
|
|
decoder := json.NewDecoder(resp.Body)
|
|
|
|
tr := new(tokenResponse)
|
|
if err = decoder.Decode(tr); err != nil {
|
|
return "", fmt.Errorf("unable to decode token response: %s", err)
|
|
}
|
|
|
|
if tr.Token == "" {
|
|
return "", errors.New("authorization server did not include a token in the response")
|
|
}
|
|
|
|
return tr.Token, nil
|
|
}
|