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