1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package transport
16
17 import (
18 "context"
19 "errors"
20 "fmt"
21 "io"
22 "net/http"
23 "net/http/httptest"
24 "net/url"
25 "strings"
26 "testing"
27
28 "github.com/google/go-containerregistry/pkg/authn"
29 "github.com/google/go-containerregistry/pkg/name"
30 )
31
32 var (
33 testReference, _ = name.NewTag("localhost:8080/user/image:latest", name.StrictValidation)
34 )
35
36 func TestTransportNoActionIfTransportIsAlreadyWrapper(t *testing.T) {
37 server := httptest.NewServer(
38 http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
39 w.Header().Set("WWW-Authenticate", `Bearer realm="http://foo.io"`)
40 http.Error(w, "Should not contact the server", http.StatusBadRequest)
41 }))
42 defer server.Close()
43 tprt := &http.Transport{
44 Proxy: func(req *http.Request) (*url.URL, error) {
45 return url.Parse(server.URL)
46 },
47 }
48
49 wTprt := &Wrapper{inner: tprt}
50
51 if _, err := NewWithContext(context.Background(), testReference.Context().Registry, nil, wTprt, []string{testReference.Scope(PullScope)}); err != nil {
52 t.Errorf("NewWithContext unexpected error %s", err)
53 }
54 }
55
56 func TestTransportSelectionAnonymous(t *testing.T) {
57
58 cannedResponse := http.Response{
59 Status: http.StatusText(http.StatusOK),
60 StatusCode: http.StatusOK,
61 Body: io.NopCloser(strings.NewReader("")),
62 }
63 recorder := newRecorder(&cannedResponse, nil)
64
65 basic := &authn.Basic{Username: "foo", Password: "bar"}
66 reg := testReference.Context().Registry
67
68 tp, err := NewWithContext(context.Background(), reg, basic, recorder, []string{testReference.Scope(PullScope)})
69 if err != nil {
70 t.Errorf("NewWithContext() = %v", err)
71 }
72
73 req, err := http.NewRequest("GET", fmt.Sprintf("http://%s/v2/anything", reg), nil)
74 if err != nil {
75 t.Fatalf("Unexpected error during NewRequest: %v", err)
76 }
77 if _, err := tp.RoundTrip(req); err != nil {
78 t.Fatalf("Unexpected error during RoundTrip: %v", err)
79 }
80
81 if got, want := len(recorder.reqs), 2; got != want {
82 t.Fatalf("expected %d requests, got %d", want, got)
83 }
84 recorded := recorder.reqs[1]
85 if got, want := recorded.URL.Scheme, "https"; got != want {
86 t.Errorf("wrong scheme, want %s got %s", want, got)
87 }
88 }
89
90 func TestTransportSelectionBasic(t *testing.T) {
91 server := httptest.NewServer(
92 http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
93 w.Header().Set("WWW-Authenticate", `Basic`)
94 http.Error(w, "Unauthorized", http.StatusUnauthorized)
95 }))
96 defer server.Close()
97 tprt := &http.Transport{
98 Proxy: func(req *http.Request) (*url.URL, error) {
99 return url.Parse(server.URL)
100 },
101 }
102
103 basic := &authn.Basic{Username: "foo", Password: "bar"}
104
105 tp, err := NewWithContext(context.Background(), testReference.Context().Registry, basic, tprt, []string{testReference.Scope(PullScope)})
106 if err != nil {
107 t.Errorf("NewWithContext() = %v", err)
108 }
109 if tpw, ok := tp.(*Wrapper); !ok {
110 t.Errorf("NewWithContext(); got %T, want *Wrapper", tp)
111 } else if _, ok := tpw.inner.(*basicTransport); !ok {
112 t.Errorf("NewWithContext(); got %T, want *basicTransport", tp)
113 }
114 }
115
116 type badAuth struct{}
117
118 func (a *badAuth) Authorization() (*authn.AuthConfig, error) {
119 return nil, errors.New("sorry dave, I'm afraid I can't let you do that")
120 }
121
122 func TestTransportBadAuth(t *testing.T) {
123 server := httptest.NewServer(
124 http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
125 w.Header().Set("WWW-Authenticate", `Bearer realm="http://foo.io"`)
126 http.Error(w, "Unauthorized", http.StatusUnauthorized)
127 }))
128 defer server.Close()
129 tprt := &http.Transport{
130 Proxy: func(req *http.Request) (*url.URL, error) {
131 return url.Parse(server.URL)
132 },
133 }
134
135 if _, err := NewWithContext(context.Background(), testReference.Context().Registry, &badAuth{}, tprt, []string{testReference.Scope(PullScope)}); err == nil {
136 t.Errorf("NewWithContext() expected err, got nil")
137 }
138 }
139
140 func TestTransportSelectionBearer(t *testing.T) {
141 request := 0
142 server := httptest.NewServer(
143 http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
144 request++
145 switch request {
146 case 1:
147
148 http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
149 case 2:
150 w.Header().Set("WWW-Authenticate", `Bearer realm="http://foo.io"`)
151 http.Error(w, "Unauthorized", http.StatusUnauthorized)
152 case 3:
153 hdr := r.Header.Get("Authorization")
154 if !strings.HasPrefix(hdr, "Basic ") {
155 t.Errorf("Header.Get(Authorization); got %v, want Basic prefix", hdr)
156 }
157 if got, want := r.FormValue("scope"), testReference.Scope(PullScope); got != want {
158 t.Errorf("FormValue(scope); got %v, want %v", got, want)
159 }
160
161
162 if got, want := r.FormValue("service"), ""; got != want {
163 t.Errorf("FormValue(service); got %q, want %q", got, want)
164 }
165 w.Write([]byte(`{"token": "dfskdjhfkhsjdhfkjhsdf"}`))
166 }
167 }))
168 defer server.Close()
169 tprt := &http.Transport{
170 Proxy: func(req *http.Request) (*url.URL, error) {
171 return url.Parse(server.URL)
172 },
173 }
174
175 basic := &authn.Basic{Username: "foo", Password: "bar"}
176 tp, err := NewWithContext(context.Background(), testReference.Context().Registry, basic, tprt, []string{testReference.Scope(PullScope)})
177 if err != nil {
178 t.Errorf("NewWithContext() = %v", err)
179 }
180 if tpw, ok := tp.(*Wrapper); !ok {
181 t.Errorf("NewWithContext(); got %T, want *Wrapper", tp)
182 } else if _, ok := tpw.inner.(*bearerTransport); !ok {
183 t.Errorf("NewWithContext(); got %T, want *bearerTransport", tp)
184 }
185 }
186
187 func TestTransportSelectionBearerMissingRealm(t *testing.T) {
188 server := httptest.NewServer(
189 http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
190 w.Header().Set("WWW-Authenticate", `Bearer service="gcr.io"`)
191 http.Error(w, "Unauthorized", http.StatusUnauthorized)
192 }))
193 defer server.Close()
194 tprt := &http.Transport{
195 Proxy: func(req *http.Request) (*url.URL, error) {
196 return url.Parse(server.URL)
197 },
198 }
199
200 basic := &authn.Basic{Username: "foo", Password: "bar"}
201 tp, err := NewWithContext(context.Background(), testReference.Context().Registry, basic, tprt, []string{testReference.Scope(PullScope)})
202 if err == nil || !strings.Contains(err.Error(), "missing realm") {
203 t.Errorf("NewWithContext() = %v, %v", tp, err)
204 }
205 }
206
207 func TestTransportSelectionBearerAuthError(t *testing.T) {
208 request := 0
209 server := httptest.NewServer(
210 http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
211 request++
212 switch request {
213 case 1:
214 w.Header().Set("WWW-Authenticate", `Bearer realm="http://foo.io"`)
215 http.Error(w, "Unauthorized", http.StatusUnauthorized)
216 case 2:
217 http.Error(w, "Oops", http.StatusInternalServerError)
218 }
219 }))
220 defer server.Close()
221 tprt := &http.Transport{
222 Proxy: func(req *http.Request) (*url.URL, error) {
223 return url.Parse(server.URL)
224 },
225 }
226
227 basic := &authn.Basic{Username: "foo", Password: "bar"}
228 tp, err := NewWithContext(context.Background(), testReference.Context().Registry, basic, tprt, []string{testReference.Scope(PullScope)})
229 if err == nil {
230 t.Errorf("NewWithContext() = %v", tp)
231 }
232 }
233
234 func TestTransportAlwaysTriesHttps(t *testing.T) {
235
236
237 count := 0
238 server := httptest.NewTLSServer(
239 http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
240 count++
241 w.Write([]byte(`{"token": "dfskdjhfkhsjdhfkjhsdf"}`))
242 }))
243 defer server.Close()
244
245 u, err := url.Parse(server.URL)
246 if err != nil {
247 t.Errorf("Unexpected error during url.Parse: %v", err)
248 }
249 registry, err := name.NewRegistry(u.Host, name.WeakValidation)
250 if err != nil {
251 t.Errorf("Unexpected error during NewRegistry: %v", err)
252 }
253
254 basic := &authn.Basic{Username: "foo", Password: "bar"}
255 tp, err := NewWithContext(context.Background(), registry, basic, server.Client().Transport, []string{testReference.Scope(PullScope)})
256 if err != nil {
257 t.Fatalf("NewWithContext() = %v, %v", tp, err)
258 }
259 if count == 0 {
260 t.Errorf("failed to call TLS localhost server")
261 }
262 }
263
View as plain text