distribution/registry_unit_test.go
4f0d95fa
 package distribution // import "github.com/docker/docker/distribution"
8dce8e99
 
 import (
7d62e40f
 	"context"
8dce8e99
 	"net/http"
 	"net/http/httptest"
79db131a
 	"net/url"
8dce8e99
 	"strings"
 	"testing"
 
3a127939
 	"github.com/docker/distribution/reference"
91e197d6
 	"github.com/docker/docker/api/types"
 	registrytypes "github.com/docker/docker/api/types/registry"
8dce8e99
 	"github.com/docker/docker/registry"
1009e6a4
 	"github.com/sirupsen/logrus"
8dce8e99
 )
 
f3df50d1
 const secretRegistryToken = "mysecrettoken"
 
 type tokenPassThruHandler struct {
 	reached       bool
 	gotToken      bool
 	shouldSend401 func(url string) bool
 }
 
 func (h *tokenPassThruHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	h.reached = true
 	if strings.Contains(r.Header.Get("Authorization"), secretRegistryToken) {
 		logrus.Debug("Detected registry token in auth header")
 		h.gotToken = true
8dce8e99
 	}
f3df50d1
 	if h.shouldSend401 == nil || h.shouldSend401(r.RequestURI) {
 		w.Header().Set("WWW-Authenticate", `Bearer realm="foorealm"`)
 		w.WriteHeader(401)
8dce8e99
 	}
f3df50d1
 }
8dce8e99
 
f3df50d1
 func testTokenPassThru(t *testing.T, ts *httptest.Server) {
79db131a
 	uri, err := url.Parse(ts.URL)
 	if err != nil {
 		t.Fatalf("could not parse url from test server: %v", err)
 	}
 
8dce8e99
 	endpoint := registry.APIEndpoint{
 		Mirror:       false,
79db131a
 		URL:          uri,
8dce8e99
 		Version:      2,
 		Official:     false,
 		TrimHostname: false,
 		TLSConfig:    nil,
 	}
3a127939
 	n, _ := reference.ParseNormalizedNamed("testremotename")
8dce8e99
 	repoInfo := &registry.RepositoryInfo{
3a127939
 		Name: n,
96c10098
 		Index: &registrytypes.IndexInfo{
8dce8e99
 			Name:     "testrepo",
 			Mirrors:  nil,
 			Secure:   false,
 			Official: false,
 		},
ffded61d
 		Official: false,
8dce8e99
 	}
 	imagePullConfig := &ImagePullConfig{
3c7676a0
 		Config: Config{
 			MetaHeaders: http.Header{},
 			AuthConfig: &types.AuthConfig{
 				RegistryToken: secretRegistryToken,
 			},
f3df50d1
 		},
3c7676a0
 		Schema2Types: ImageTypes,
8dce8e99
 	}
572ce802
 	puller, err := newPuller(endpoint, repoInfo, imagePullConfig)
8dce8e99
 	if err != nil {
 		t.Fatal(err)
 	}
 	p := puller.(*v2Puller)
a57478d6
 	ctx := context.Background()
 	p.repo, _, err = NewV2Repository(ctx, p.repoInfo, p.endpoint, p.config.MetaHeaders, p.config.AuthConfig, "pull")
8dce8e99
 	if err != nil {
 		t.Fatal(err)
 	}
 
 	logrus.Debug("About to pull")
 	// We expect it to fail, since we haven't mock'd the full registry exchange in our handler above
 	tag, _ := reference.WithTag(n, "tag_goes_here")
337ba71f
 	_ = p.pullV2Repository(ctx, tag, nil)
f3df50d1
 }
8dce8e99
 
f3df50d1
 func TestTokenPassThru(t *testing.T) {
 	handler := &tokenPassThruHandler{shouldSend401: func(url string) bool { return url == "/v2/" }}
 	ts := httptest.NewServer(handler)
 	defer ts.Close()
 
 	testTokenPassThru(t, ts)
 
 	if !handler.reached {
 		t.Fatal("Handler not reached")
 	}
 	if !handler.gotToken {
8dce8e99
 		t.Fatal("Failed to receive registry token")
 	}
f3df50d1
 }
 
 func TestTokenPassThruDifferentHost(t *testing.T) {
 	handler := new(tokenPassThruHandler)
 	ts := httptest.NewServer(handler)
 	defer ts.Close()
 
 	tsredirect := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		if r.RequestURI == "/v2/" {
 			w.Header().Set("WWW-Authenticate", `Bearer realm="foorealm"`)
 			w.WriteHeader(401)
 			return
 		}
 		http.Redirect(w, r, ts.URL+r.URL.Path, http.StatusMovedPermanently)
 	}))
 	defer tsredirect.Close()
8dce8e99
 
f3df50d1
 	testTokenPassThru(t, tsredirect)
 
 	if !handler.reached {
 		t.Fatal("Handler not reached")
 	}
 	if handler.gotToken {
 		t.Fatal("Redirect should not forward Authorization header to another host")
 	}
8dce8e99
 }