@@ -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,46 @@ 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
+ // Now test the skipped path with authentication.
300
+ reqSkippedWithAuth , err := http .NewRequest (method , urlToSkip , nil )
301
+ require .NoError (t , err )
302
+ reqSkippedWithAuth .Header .Add ("Authorization" , "foobar" )
303
+
304
+ respSkippedWithAuth , err := client .Do (reqSkippedWithAuth )
305
+ require .NoError (t , err )
306
+ require .Equal (t , "200 OK" , respSkippedWithAuth .Status )
307
+ defer closeOrFail (t , respSkippedWithAuth .Body )
308
+ bodyBytesSkippedWithAuth , err := io .ReadAll (respSkippedWithAuth .Body )
309
+ require .NoError (t , err )
310
+ require .Equal (t , testHTTPResponseBody , string (bodyBytesSkippedWithAuth ))
311
+ }
312
+
264
313
// Make sure that if the Auth header is set, the client's request is
265
- // proxied to the backend service.
314
+ // proxied to the backend service for a non-skipped, non-whitelisted path .
266
315
req , err = http .NewRequest (method , url , nil )
267
316
require .NoError (t , err )
268
317
req .Header .Add ("Authorization" , "foobar" )
@@ -297,6 +346,12 @@ func TestProxyGRPC(t *testing.T) {
297
346
authWhitelist : []string {
298
347
"^/proxy_test\\ .Greeter/SayHelloNoAuth.*$" ,
299
348
},
349
+ }, {
350
+ name : "gRPC no whitelist with skip for SayHello" ,
351
+ auth : "on" ,
352
+ authSkipInvoiceCreationPaths : []string {
353
+ `^/proxy_test[.]Greeter/SayHello.*$` ,
354
+ },
300
355
}}
301
356
302
357
for _ , tc := range testCases {
@@ -343,13 +398,14 @@ func runGRPCTest(t *testing.T, tc *testCase) {
343
398
344
399
// Create a list of services to proxy between.
345
400
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 ,
401
+ Address : testTargetServiceAddress ,
402
+ HostRegexp : testHostRegexp ,
403
+ PathRegexp : testPathRegexpGRPC ,
404
+ Protocol : "https" ,
405
+ TLSCertPath : certFile ,
406
+ Auth : tc .auth ,
407
+ AuthWhitelistPaths : tc .authWhitelist ,
408
+ AuthSkipInvoiceCreationPaths : tc .authSkipInvoiceCreationPaths ,
353
409
}}
354
410
355
411
// Create the proxy server and start serving on TLS.
@@ -393,17 +449,24 @@ func runGRPCTest(t *testing.T, tc *testCase) {
393
449
grpc .Trailer (& captureMetadata ),
394
450
)
395
451
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
- )
452
+ if len (tc .authSkipInvoiceCreationPaths ) > 0 {
453
+ statusErr , ok := status .FromError (err )
454
+ require .True (t , ok )
455
+ require .Equal (t , codes .Internal , statusErr .Code ())
456
+ require .Equal (t , "unauthorized" , statusErr .Message ())
457
+ } else {
458
+ require .True (t , l402 .IsPaymentRequired (err ))
459
+
460
+ // We expect the WWW-Authenticate header field to be set to an L402
461
+ // auth response.
462
+ expectedHeaderContent , _ := mockAuth .FreshChallengeHeader ("" , 0 )
463
+ capturedHeader := captureMetadata .Get ("WWW-Authenticate" )
464
+ require .Len (t , capturedHeader , 2 )
465
+ require .Equal (
466
+ t , expectedHeaderContent .Values ("WWW-Authenticate" ),
467
+ capturedHeader ,
468
+ )
469
+ }
407
470
408
471
// Make sure that if we query an URL that is on the whitelist, we don't
409
472
// get the 402 response.
0 commit comments