@@ -48,10 +48,11 @@ var (
48
48
)
49
49
50
50
type testCase struct {
51
- name string
52
- auth auth.Level
53
- authWhitelist []string
54
- wantBackendErr bool
51
+ name string
52
+ auth auth.Level
53
+ authWhitelist []string
54
+ authSkipInvoiceCreationPaths []string
55
+ wantBackendErr bool
55
56
}
56
57
57
58
// helloServer is a simple server that implements the GreeterServer interface.
@@ -98,6 +99,15 @@ func TestProxyHTTP(t *testing.T) {
98
99
name : "with whitelist" ,
99
100
auth : "on" ,
100
101
authWhitelist : []string {"^/http/white.*$" },
102
+ }, {
103
+ name : "no whitelist with skip" ,
104
+ auth : "on" ,
105
+ authSkipInvoiceCreationPaths : []string {"^/http/skip.*$" },
106
+ }, {
107
+ name : "with whitelist with skip" ,
108
+ auth : "on" ,
109
+ authWhitelist : []string {"^/http/white.*$" },
110
+ authSkipInvoiceCreationPaths : []string {"^/http/skip.*$" },
101
111
}}
102
112
103
113
for _ , tc := range testCases {
@@ -182,12 +192,13 @@ func TestProxyHTTPBlocklist(t *testing.T) {
182
192
func runHTTPTest (t * testing.T , tc * testCase , method string ) {
183
193
// Create a list of services to proxy between.
184
194
services := []* proxy.Service {{
185
- Address : testTargetServiceAddress ,
186
- HostRegexp : testHostRegexp ,
187
- PathRegexp : testPathRegexpHTTP ,
188
- Protocol : "http" ,
189
- Auth : tc .auth ,
190
- AuthWhitelistPaths : tc .authWhitelist ,
195
+ Address : testTargetServiceAddress ,
196
+ HostRegexp : testHostRegexp ,
197
+ PathRegexp : testPathRegexpHTTP ,
198
+ Protocol : "http" ,
199
+ Auth : tc .auth ,
200
+ AuthWhitelistPaths : tc .authWhitelist ,
201
+ AuthSkipInvoiceCreationPaths : tc .authSkipInvoiceCreationPaths ,
191
202
}}
192
203
193
204
mockAuth := auth .NewMockAuthenticator ()
@@ -261,8 +272,33 @@ func runHTTPTest(t *testing.T, tc *testCase, method string) {
261
272
require .EqualValues (t , len (bodyBytes ), resp .ContentLength )
262
273
}
263
274
275
+ // Make sure that if we query a URL that is on the skip invoice
276
+ // creation list, we get a 401 if auth fails.
277
+ if len (tc .authSkipInvoiceCreationPaths ) > 0 {
278
+ urlToSkip := fmt .Sprintf ("http://%s/http/skip" , testProxyAddr )
279
+ reqToSkip , err := http .NewRequest (method , urlToSkip , nil )
280
+ require .NoError (t , err )
281
+
282
+ if method == "POST" {
283
+ reqToSkip .Header .Add ("Content-Type" , "application/json" )
284
+ reqToSkip .Body = io .NopCloser (strings .NewReader (`{}` ))
285
+ }
286
+
287
+ respSkipped , err := client .Do (reqToSkip )
288
+ require .NoError (t , err )
289
+
290
+ require .Equal (t , http .StatusUnauthorized , respSkipped .StatusCode )
291
+ require .Equal (t , "401 Unauthorized" , respSkipped .Status )
292
+
293
+ bodySkippedContent , err := io .ReadAll (respSkipped .Body )
294
+ require .NoError (t , err )
295
+ require .Equal (t , "unauthorized\n " , string (bodySkippedContent ))
296
+ require .EqualValues (t , len (bodySkippedContent ), respSkipped .ContentLength )
297
+ _ = respSkipped .Body .Close ()
298
+ }
299
+
264
300
// Make sure that if the Auth header is set, the client's request is
265
- // proxied to the backend service.
301
+ // proxied to the backend service for a non-skipped, non-whitelisted path .
266
302
req , err = http .NewRequest (method , url , nil )
267
303
require .NoError (t , err )
268
304
req .Header .Add ("Authorization" , "foobar" )
@@ -297,6 +333,12 @@ func TestProxyGRPC(t *testing.T) {
297
333
authWhitelist : []string {
298
334
"^/proxy_test\\ .Greeter/SayHelloNoAuth.*$" ,
299
335
},
336
+ }, {
337
+ name : "gRPC no whitelist with skip for SayHello" ,
338
+ auth : "on" ,
339
+ authSkipInvoiceCreationPaths : []string {
340
+ `^/proxy_test[.]Greeter/SayHello.*$` ,
341
+ },
300
342
}}
301
343
302
344
for _ , tc := range testCases {
@@ -343,13 +385,14 @@ func runGRPCTest(t *testing.T, tc *testCase) {
343
385
344
386
// Create a list of services to proxy between.
345
387
services := []* proxy.Service {{
346
- Address : testTargetServiceAddress ,
347
- HostRegexp : testHostRegexp ,
348
- PathRegexp : testPathRegexpGRPC ,
349
- Protocol : "https" ,
350
- TLSCertPath : certFile ,
351
- Auth : tc .auth ,
352
- AuthWhitelistPaths : tc .authWhitelist ,
388
+ Address : testTargetServiceAddress ,
389
+ HostRegexp : testHostRegexp ,
390
+ PathRegexp : testPathRegexpGRPC ,
391
+ Protocol : "https" ,
392
+ TLSCertPath : certFile ,
393
+ Auth : tc .auth ,
394
+ AuthWhitelistPaths : tc .authWhitelist ,
395
+ AuthSkipInvoiceCreationPaths : tc .authSkipInvoiceCreationPaths ,
353
396
}}
354
397
355
398
// Create the proxy server and start serving on TLS.
@@ -393,17 +436,24 @@ func runGRPCTest(t *testing.T, tc *testCase) {
393
436
grpc .Trailer (& captureMetadata ),
394
437
)
395
438
require .Error (t , err )
396
- require .True (t , l402 .IsPaymentRequired (err ))
397
-
398
- // We expect the WWW-Authenticate header field to be set to an L402
399
- // auth response.
400
- expectedHeaderContent , _ := mockAuth .FreshChallengeHeader ("" , 0 )
401
- capturedHeader := captureMetadata .Get ("WWW-Authenticate" )
402
- require .Len (t , capturedHeader , 2 )
403
- require .Equal (
404
- t , expectedHeaderContent .Values ("WWW-Authenticate" ),
405
- capturedHeader ,
406
- )
439
+ if len (tc .authSkipInvoiceCreationPaths ) > 0 {
440
+ statusErr , ok := status .FromError (err )
441
+ require .True (t , ok )
442
+ require .Equal (t , codes .Internal , statusErr .Code ())
443
+ require .Equal (t , "unauthorized" , statusErr .Message ())
444
+ } else {
445
+ require .True (t , l402 .IsPaymentRequired (err ))
446
+
447
+ // We expect the WWW-Authenticate header field to be set to an L402
448
+ // auth response.
449
+ expectedHeaderContent , _ := mockAuth .FreshChallengeHeader ("" , 0 )
450
+ capturedHeader := captureMetadata .Get ("WWW-Authenticate" )
451
+ require .Len (t , capturedHeader , 2 )
452
+ require .Equal (
453
+ t , expectedHeaderContent .Values ("WWW-Authenticate" ),
454
+ capturedHeader ,
455
+ )
456
+ }
407
457
408
458
// Make sure that if we query an URL that is on the whitelist, we don't
409
459
// get the 402 response.
0 commit comments