github.com/skf/moby@v1.13.1/distribution/registry_unit_test.go (about) 1 package distribution 2 3 import ( 4 "net/http" 5 "net/http/httptest" 6 "net/url" 7 "os" 8 "strings" 9 "testing" 10 11 "github.com/Sirupsen/logrus" 12 "github.com/docker/docker/api/types" 13 registrytypes "github.com/docker/docker/api/types/registry" 14 "github.com/docker/docker/reference" 15 "github.com/docker/docker/registry" 16 "github.com/docker/docker/utils" 17 "golang.org/x/net/context" 18 ) 19 20 const secretRegistryToken = "mysecrettoken" 21 22 type tokenPassThruHandler struct { 23 reached bool 24 gotToken bool 25 shouldSend401 func(url string) bool 26 } 27 28 func (h *tokenPassThruHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 29 h.reached = true 30 if strings.Contains(r.Header.Get("Authorization"), secretRegistryToken) { 31 logrus.Debug("Detected registry token in auth header") 32 h.gotToken = true 33 } 34 if h.shouldSend401 == nil || h.shouldSend401(r.RequestURI) { 35 w.Header().Set("WWW-Authenticate", `Bearer realm="foorealm"`) 36 w.WriteHeader(401) 37 } 38 } 39 40 func testTokenPassThru(t *testing.T, ts *httptest.Server) { 41 tmp, err := utils.TestDirectory("") 42 if err != nil { 43 t.Fatal(err) 44 } 45 defer os.RemoveAll(tmp) 46 47 uri, err := url.Parse(ts.URL) 48 if err != nil { 49 t.Fatalf("could not parse url from test server: %v", err) 50 } 51 52 endpoint := registry.APIEndpoint{ 53 Mirror: false, 54 URL: uri, 55 Version: 2, 56 Official: false, 57 TrimHostname: false, 58 TLSConfig: nil, 59 //VersionHeader: "verheader", 60 } 61 n, _ := reference.ParseNamed("testremotename") 62 repoInfo := ®istry.RepositoryInfo{ 63 Named: n, 64 Index: ®istrytypes.IndexInfo{ 65 Name: "testrepo", 66 Mirrors: nil, 67 Secure: false, 68 Official: false, 69 }, 70 Official: false, 71 } 72 imagePullConfig := &ImagePullConfig{ 73 Config: Config{ 74 MetaHeaders: http.Header{}, 75 AuthConfig: &types.AuthConfig{ 76 RegistryToken: secretRegistryToken, 77 }, 78 }, 79 Schema2Types: ImageTypes, 80 } 81 puller, err := newPuller(endpoint, repoInfo, imagePullConfig) 82 if err != nil { 83 t.Fatal(err) 84 } 85 p := puller.(*v2Puller) 86 ctx := context.Background() 87 p.repo, _, err = NewV2Repository(ctx, p.repoInfo, p.endpoint, p.config.MetaHeaders, p.config.AuthConfig, "pull") 88 if err != nil { 89 t.Fatal(err) 90 } 91 92 logrus.Debug("About to pull") 93 // We expect it to fail, since we haven't mock'd the full registry exchange in our handler above 94 tag, _ := reference.WithTag(n, "tag_goes_here") 95 _ = p.pullV2Repository(ctx, tag) 96 } 97 98 func TestTokenPassThru(t *testing.T) { 99 handler := &tokenPassThruHandler{shouldSend401: func(url string) bool { return url == "/v2/" }} 100 ts := httptest.NewServer(handler) 101 defer ts.Close() 102 103 testTokenPassThru(t, ts) 104 105 if !handler.reached { 106 t.Fatal("Handler not reached") 107 } 108 if !handler.gotToken { 109 t.Fatal("Failed to receive registry token") 110 } 111 } 112 113 func TestTokenPassThruDifferentHost(t *testing.T) { 114 handler := new(tokenPassThruHandler) 115 ts := httptest.NewServer(handler) 116 defer ts.Close() 117 118 tsredirect := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 119 if r.RequestURI == "/v2/" { 120 w.Header().Set("WWW-Authenticate", `Bearer realm="foorealm"`) 121 w.WriteHeader(401) 122 return 123 } 124 http.Redirect(w, r, ts.URL+r.URL.Path, http.StatusMovedPermanently) 125 })) 126 defer tsredirect.Close() 127 128 testTokenPassThru(t, tsredirect) 129 130 if !handler.reached { 131 t.Fatal("Handler not reached") 132 } 133 if handler.gotToken { 134 t.Fatal("Redirect should not forward Authorization header to another host") 135 } 136 }