diff --git a/docs/registry.go b/docs/registry.go index 6aea458e..c39ecfe5 100644 --- a/docs/registry.go +++ b/docs/registry.go @@ -160,7 +160,9 @@ func (r *Registry) GetRemoteHistory(imgID, registry string, token []string) ([]s if err != nil { return nil, err } - req.Header.Set("Authorization", "Token "+strings.Join(token, ", ")) + if req.Header.Get("Authorization") == "" { // Don't override + req.Header.Set("Authorization", "Token "+strings.Join(token, ",")) + } res, err := doWithCookies(r.client, req) if err != nil { return nil, err @@ -193,7 +195,9 @@ func (r *Registry) LookupRemoteImage(imgID, registry string, token []string) boo if err != nil { return false } - req.Header.Set("Authorization", "Token "+strings.Join(token, ", ")) + if req.Header.Get("Authorization") == "" { // Don't override + req.Header.Set("Authorization", "Token "+strings.Join(token, ",")) + } res, err := doWithCookies(r.client, req) if err != nil { return false @@ -209,7 +213,9 @@ func (r *Registry) GetRemoteImageJSON(imgID, registry string, token []string) ([ if err != nil { return nil, -1, fmt.Errorf("Failed to download json: %s", err) } - req.Header.Set("Authorization", "Token "+strings.Join(token, ", ")) + if req.Header.Get("Authorization") == "" { // Don't override + req.Header.Set("Authorization", "Token "+strings.Join(token, ",")) + } res, err := doWithCookies(r.client, req) if err != nil { return nil, -1, fmt.Errorf("Failed to download json: %s", err) @@ -236,7 +242,9 @@ func (r *Registry) GetRemoteImageLayer(imgID, registry string, token []string) ( if err != nil { return nil, fmt.Errorf("Error while getting from the server: %s\n", err) } - req.Header.Set("Authorization", "Token "+strings.Join(token, ", ")) + if req.Header.Get("Authorization") == "" { // Don't override + req.Header.Set("Authorization", "Token "+strings.Join(token, ",")) + } res, err := doWithCookies(r.client, req) if err != nil { return nil, err @@ -262,7 +270,9 @@ func (r *Registry) GetRemoteTags(registries []string, repository string, token [ if err != nil { return nil, err } - req.Header.Set("Authorization", "Token "+strings.Join(token, ", ")) + if req.Header.Get("Authorization") == "" { // Don't override + req.Header.Set("Authorization", "Token "+strings.Join(token, ",")) + } res, err := doWithCookies(r.client, req) if err != nil { return nil, err @@ -290,7 +300,8 @@ func (r *Registry) GetRemoteTags(registries []string, repository string, token [ return nil, fmt.Errorf("Could not reach any registry endpoint") } -func (r *Registry) GetRepositoryData(indexEp, remote string) (*RepositoryData, error) { +func (r *Registry) GetRepositoryData(remote string) (*RepositoryData, error) { + indexEp := r.indexEndpoint repositoryTarget := fmt.Sprintf("%srepositories/%s/images", indexEp, remote) utils.Debugf("[registry] Calling GET %s", repositoryTarget) @@ -364,7 +375,9 @@ func (r *Registry) PushImageChecksumRegistry(imgData *ImgData, registry string, if err != nil { return err } - req.Header.Set("Authorization", "Token "+strings.Join(token, ",")) + if req.Header.Get("Authorization") == "" { // Don't override + req.Header.Set("Authorization", "Token "+strings.Join(token, ",")) + } req.Header.Set("X-Docker-Checksum", imgData.Checksum) res, err := doWithCookies(r.client, req) @@ -401,7 +414,9 @@ func (r *Registry) PushImageJSONRegistry(imgData *ImgData, jsonRaw []byte, regis return err } req.Header.Add("Content-type", "application/json") - req.Header.Set("Authorization", "Token "+strings.Join(token, ",")) + if req.Header.Get("Authorization") == "" { // Don't override + req.Header.Set("Authorization", "Token "+strings.Join(token, ",")) + } res, err := doWithCookies(r.client, req) if err != nil { @@ -436,7 +451,9 @@ func (r *Registry) PushImageLayerRegistry(imgID string, layer io.Reader, registr } req.ContentLength = -1 req.TransferEncoding = []string{"chunked"} - req.Header.Set("Authorization", "Token "+strings.Join(token, ",")) + if req.Header.Get("Authorization") == "" { // Don't override + req.Header.Set("Authorization", "Token "+strings.Join(token, ",")) + } res, err := doWithCookies(r.client, req) if err != nil { return "", fmt.Errorf("Failed to upload layer: %s", err) @@ -465,7 +482,9 @@ func (r *Registry) PushRegistryTag(remote, revision, tag, registry string, token return err } req.Header.Add("Content-type", "application/json") - req.Header.Set("Authorization", "Token "+strings.Join(token, ",")) + if req.Header.Get("Authorization") == "" { // Don't override + req.Header.Set("Authorization", "Token "+strings.Join(token, ",")) + } req.ContentLength = int64(len(revision)) res, err := doWithCookies(r.client, req) if err != nil { @@ -478,8 +497,9 @@ func (r *Registry) PushRegistryTag(remote, revision, tag, registry string, token return nil } -func (r *Registry) PushImageJSONIndex(indexEp, remote string, imgList []*ImgData, validate bool, regs []string) (*RepositoryData, error) { +func (r *Registry) PushImageJSONIndex(remote string, imgList []*ImgData, validate bool, regs []string) (*RepositoryData, error) { cleanImgList := []*ImgData{} + indexEp := r.indexEndpoint if validate { for _, elem := range imgList { @@ -583,6 +603,7 @@ func (r *Registry) PushImageJSONIndex(indexEp, remote string, imgList []*ImgData } func (r *Registry) SearchRepositories(term string) (*SearchResults, error) { + utils.Debugf("Index server: %s", r.indexEndpoint) u := auth.IndexServerAddress() + "search?q=" + url.QueryEscape(term) req, err := r.reqFactory.NewRequest("GET", u, nil) if err != nil { @@ -644,12 +665,13 @@ type ImgData struct { } type Registry struct { - client *http.Client - authConfig *auth.AuthConfig - reqFactory *utils.HTTPRequestFactory + client *http.Client + authConfig *auth.AuthConfig + reqFactory *utils.HTTPRequestFactory + indexEndpoint string } -func NewRegistry(root string, authConfig *auth.AuthConfig, factory *utils.HTTPRequestFactory) (r *Registry, err error) { +func NewRegistry(authConfig *auth.AuthConfig, factory *utils.HTTPRequestFactory, indexEndpoint string) (r *Registry, err error) { httpTransport := &http.Transport{ DisableKeepAlives: true, Proxy: http.ProxyFromEnvironment, @@ -660,12 +682,22 @@ func NewRegistry(root string, authConfig *auth.AuthConfig, factory *utils.HTTPRe client: &http.Client{ Transport: httpTransport, }, + indexEndpoint: indexEndpoint, } r.client.Jar, err = cookiejar.New(nil) if err != nil { return nil, err } + // If we're working with a private registry over HTTPS, send Basic Auth headers + // alongside our requests. + if indexEndpoint != auth.IndexServerAddress() && strings.HasPrefix(indexEndpoint, "https://") { + utils.Debugf("Endpoint %s is eligible for private registry auth. Enabling decorator.", indexEndpoint) + dec := utils.NewHTTPAuthDecorator(authConfig.Username, authConfig.Password) + factory.AddDecorator(dec) + } + r.reqFactory = factory return r, nil } + diff --git a/docs/registry_test.go b/docs/registry_test.go index fb43da66..69eb25b2 100644 --- a/docs/registry_test.go +++ b/docs/registry_test.go @@ -15,7 +15,7 @@ var ( func spawnTestRegistry(t *testing.T) *Registry { authConfig := &auth.AuthConfig{} - r, err := NewRegistry("", authConfig, utils.NewHTTPRequestFactory()) + r, err := NewRegistry(authConfig, utils.NewHTTPRequestFactory(), makeURL("/v1/")) if err != nil { t.Fatal(err) } @@ -99,7 +99,7 @@ func TestGetRemoteTags(t *testing.T) { func TestGetRepositoryData(t *testing.T) { r := spawnTestRegistry(t) - data, err := r.GetRepositoryData(makeURL("/v1/"), "foo42/bar") + data, err := r.GetRepositoryData("foo42/bar") if err != nil { t.Fatal(err) } @@ -168,15 +168,14 @@ func TestPushImageJSONIndex(t *testing.T) { Checksum: "sha256:bea7bf2e4bacd479344b737328db47b18880d09096e6674165533aa994f5e9f2", }, } - ep := makeURL("/v1/") - repoData, err := r.PushImageJSONIndex(ep, "foo42/bar", imgData, false, nil) + repoData, err := r.PushImageJSONIndex("foo42/bar", imgData, false, nil) if err != nil { t.Fatal(err) } if repoData == nil { t.Fatal("Expected RepositoryData object") } - repoData, err = r.PushImageJSONIndex(ep, "foo42/bar", imgData, true, []string{ep}) + repoData, err = r.PushImageJSONIndex("foo42/bar", imgData, true, []string{r.indexEndpoint}) if err != nil { t.Fatal(err) }