Signed-off-by: Tibor Vass <tibor@docker.com>
Tibor Vass authored on 2016/01/27 07:14:13... | ... |
@@ -16,24 +16,27 @@ import ( |
16 | 16 |
"golang.org/x/net/context" |
17 | 17 |
) |
18 | 18 |
|
19 |
-func TestTokenPassThru(t *testing.T) { |
|
20 |
- authConfig := &types.AuthConfig{ |
|
21 |
- RegistryToken: "mysecrettoken", |
|
19 |
+const secretRegistryToken = "mysecrettoken" |
|
20 |
+ |
|
21 |
+type tokenPassThruHandler struct { |
|
22 |
+ reached bool |
|
23 |
+ gotToken bool |
|
24 |
+ shouldSend401 func(url string) bool |
|
25 |
+} |
|
26 |
+ |
|
27 |
+func (h *tokenPassThruHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
28 |
+ h.reached = true |
|
29 |
+ if strings.Contains(r.Header.Get("Authorization"), secretRegistryToken) { |
|
30 |
+ logrus.Debug("Detected registry token in auth header") |
|
31 |
+ h.gotToken = true |
|
22 | 32 |
} |
23 |
- gotToken := false |
|
24 |
- handler := func(w http.ResponseWriter, r *http.Request) { |
|
25 |
- if strings.Contains(r.Header.Get("Authorization"), authConfig.RegistryToken) { |
|
26 |
- logrus.Debug("Detected registry token in auth header") |
|
27 |
- gotToken = true |
|
28 |
- } |
|
29 |
- if r.RequestURI == "/v2/" { |
|
30 |
- w.Header().Set("WWW-Authenticate", `Bearer realm="foorealm"`) |
|
31 |
- w.WriteHeader(401) |
|
32 |
- } |
|
33 |
+ if h.shouldSend401 == nil || h.shouldSend401(r.RequestURI) { |
|
34 |
+ w.Header().Set("WWW-Authenticate", `Bearer realm="foorealm"`) |
|
35 |
+ w.WriteHeader(401) |
|
33 | 36 |
} |
34 |
- ts := httptest.NewServer(http.HandlerFunc(handler)) |
|
35 |
- defer ts.Close() |
|
37 |
+} |
|
36 | 38 |
|
39 |
+func testTokenPassThru(t *testing.T, ts *httptest.Server) { |
|
37 | 40 |
tmp, err := utils.TestDirectory("") |
38 | 41 |
if err != nil { |
39 | 42 |
t.Fatal(err) |
... | ... |
@@ -62,7 +65,9 @@ func TestTokenPassThru(t *testing.T) { |
62 | 62 |
} |
63 | 63 |
imagePullConfig := &ImagePullConfig{ |
64 | 64 |
MetaHeaders: http.Header{}, |
65 |
- AuthConfig: authConfig, |
|
65 |
+ AuthConfig: &types.AuthConfig{ |
|
66 |
+ RegistryToken: secretRegistryToken, |
|
67 |
+ }, |
|
66 | 68 |
} |
67 | 69 |
puller, err := newPuller(endpoint, repoInfo, imagePullConfig) |
68 | 70 |
if err != nil { |
... | ... |
@@ -79,9 +84,44 @@ func TestTokenPassThru(t *testing.T) { |
79 | 79 |
// We expect it to fail, since we haven't mock'd the full registry exchange in our handler above |
80 | 80 |
tag, _ := reference.WithTag(n, "tag_goes_here") |
81 | 81 |
_ = p.pullV2Repository(ctx, tag) |
82 |
+} |
|
82 | 83 |
|
83 |
- if !gotToken { |
|
84 |
+func TestTokenPassThru(t *testing.T) { |
|
85 |
+ handler := &tokenPassThruHandler{shouldSend401: func(url string) bool { return url == "/v2/" }} |
|
86 |
+ ts := httptest.NewServer(handler) |
|
87 |
+ defer ts.Close() |
|
88 |
+ |
|
89 |
+ testTokenPassThru(t, ts) |
|
90 |
+ |
|
91 |
+ if !handler.reached { |
|
92 |
+ t.Fatal("Handler not reached") |
|
93 |
+ } |
|
94 |
+ if !handler.gotToken { |
|
84 | 95 |
t.Fatal("Failed to receive registry token") |
85 | 96 |
} |
97 |
+} |
|
98 |
+ |
|
99 |
+func TestTokenPassThruDifferentHost(t *testing.T) { |
|
100 |
+ handler := new(tokenPassThruHandler) |
|
101 |
+ ts := httptest.NewServer(handler) |
|
102 |
+ defer ts.Close() |
|
103 |
+ |
|
104 |
+ tsredirect := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
105 |
+ if r.RequestURI == "/v2/" { |
|
106 |
+ w.Header().Set("WWW-Authenticate", `Bearer realm="foorealm"`) |
|
107 |
+ w.WriteHeader(401) |
|
108 |
+ return |
|
109 |
+ } |
|
110 |
+ http.Redirect(w, r, ts.URL+r.URL.Path, http.StatusMovedPermanently) |
|
111 |
+ })) |
|
112 |
+ defer tsredirect.Close() |
|
86 | 113 |
|
114 |
+ testTokenPassThru(t, tsredirect) |
|
115 |
+ |
|
116 |
+ if !handler.reached { |
|
117 |
+ t.Fatal("Handler not reached") |
|
118 |
+ } |
|
119 |
+ if handler.gotToken { |
|
120 |
+ t.Fatal("Redirect should not forward Authorization header to another host") |
|
121 |
+ } |
|
87 | 122 |
} |