@@ -13,6 +13,7 @@ import (
13
13
"time"
14
14
15
15
zerr "zotregistry.dev/zot/errors"
16
+ "zotregistry.dev/zot/pkg/api/constants"
16
17
"zotregistry.dev/zot/pkg/common"
17
18
"zotregistry.dev/zot/pkg/log"
18
19
)
@@ -165,7 +166,7 @@ func (httpClient *Client) Ping() bool {
165
166
return false
166
167
}
167
168
168
- httpClient .getAuthType (resp )
169
+ httpClient .authType = getAuthType (resp )
169
170
170
171
if resp .StatusCode >= http .StatusOK && resp .StatusCode <= http .StatusForbidden {
171
172
return true
@@ -220,21 +221,6 @@ func (httpClient *Client) MakeGetRequest(ctx context.Context, resultPtr interfac
220
221
return body , resp .Header , resp .StatusCode , err
221
222
}
222
223
223
- func (httpClient * Client ) getAuthType (resp * http.Response ) {
224
- authHeader := resp .Header .Get ("www-authenticate" )
225
-
226
- authHeaderLower := strings .ToLower (authHeader )
227
-
228
- //nolint: gocritic
229
- if strings .Contains (authHeaderLower , "bearer" ) {
230
- httpClient .authType = tokenAuth
231
- } else if strings .Contains (authHeaderLower , "basic" ) {
232
- httpClient .authType = basicAuth
233
- } else {
234
- httpClient .authType = noneAuth
235
- }
236
- }
237
-
238
224
func (httpClient * Client ) setupAuth (req * http.Request , namespace string ) error {
239
225
if httpClient .authType == tokenAuth {
240
226
token , err := httpClient .getToken (req .URL .String (), namespace )
@@ -298,7 +284,15 @@ func (httpClient *Client) makeAndDoRequest(method, mediaType, namespace, urlStr
298
284
return nil , nil , err
299
285
}
300
286
301
- if err := httpClient .setupAuth (req , namespace ); err != nil {
287
+ err = httpClient .setupAuth (req , namespace )
288
+ if err != nil {
289
+ // harbor catalog requests return basicAuth by default, even if bearer is used on the rest of endpoints.
290
+ if errors .Is (err , zerr .ErrUnexpectedAuthHeader ) &&
291
+ strings .Contains (urlStr , constants .ExtCatalogPrefix ) {
292
+ // try with basic auth
293
+ return httpClient .get (context .Background (), urlStr , true )
294
+ }
295
+
302
296
return nil , nil , err
303
297
}
304
298
@@ -371,7 +365,7 @@ func (httpClient *Client) getToken(urlStr, namespace string) (*bearerToken, erro
371
365
return nil , err
372
366
}
373
367
374
- challengeParams , err := parseAuthHeader (resp )
368
+ challengeParams , err := parseBearerAuthHeader (resp )
375
369
if err != nil {
376
370
return nil , err
377
371
}
@@ -384,6 +378,21 @@ func (httpClient *Client) getToken(urlStr, namespace string) (*bearerToken, erro
384
378
return httpClient .getTokenFromURL (tokenURL .String (), namespace )
385
379
}
386
380
381
+ func getAuthType (resp * http.Response ) authType {
382
+ authHeader := resp .Header .Get ("www-authenticate" )
383
+
384
+ authHeaderLower := strings .ToLower (authHeader )
385
+
386
+ //nolint: gocritic
387
+ if strings .Contains (authHeaderLower , "bearer" ) {
388
+ return tokenAuth
389
+ } else if strings .Contains (authHeaderLower , "basic" ) {
390
+ return basicAuth
391
+ } else {
392
+ return noneAuth
393
+ }
394
+ }
395
+
387
396
func newBearerToken (blob []byte ) (* bearerToken , error ) {
388
397
token := new (bearerToken )
389
398
if err := json .Unmarshal (blob , & token ); err != nil {
@@ -426,14 +435,18 @@ func getTokenURLFromChallengeParams(params challengeParams, account string) (*ur
426
435
return parsedRealm , nil
427
436
}
428
437
429
- func parseAuthHeader (resp * http.Response ) (challengeParams , error ) {
438
+ func parseBearerAuthHeader (resp * http.Response ) (challengeParams , error ) {
430
439
authHeader := resp .Header .Get ("www-authenticate" )
431
440
432
441
authHeaderSlice := strings .Split (authHeader , "," )
433
442
434
443
params := challengeParams {}
435
444
436
445
for _ , elem := range authHeaderSlice {
446
+ if strings .Contains (strings .ToLower (elem ), "basic" ) {
447
+ return params , zerr .ErrUnexpectedAuthHeader
448
+ }
449
+
437
450
if strings .Contains (strings .ToLower (elem ), "bearer" ) {
438
451
elem = strings .Split (elem , " " )[1 ]
439
452
}
@@ -469,7 +482,7 @@ func parseAuthHeader(resp *http.Response) (challengeParams, error) {
469
482
func needsRetryWithUpdatedScope (err error , resp * http.Response ) (bool , challengeParams ) {
470
483
params := challengeParams {}
471
484
if err == nil && resp .StatusCode == http .StatusUnauthorized {
472
- params , err = parseAuthHeader (resp )
485
+ params , err = parseBearerAuthHeader (resp )
473
486
if err != nil {
474
487
return false , params
475
488
}
0 commit comments