diff --git a/go.mod b/go.mod index e91efd27c7ba03ad46c059187918f59e60f1ae01..29f89e3c5d0a88858dcf64e3e2e35331c83a7ff8 100644 --- a/go.mod +++ b/go.mod @@ -67,6 +67,7 @@ require ( github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d // indirect github.com/imdario/mergo v0.3.5 // indirect github.com/isbrick/http-client v0.0.0-20210321135403-0a5df00fdb84 // indirect + github.com/jarcoal/httpmock v1.2.0 // indirect github.com/json-iterator/go v1.1.8 // indirect github.com/kr/text v0.2.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect diff --git a/internal/core/settings/registryhub.go b/internal/core/settings/registryhub.go index c3070bf4689a410f25eb86be46c27046fc92f356..3d26bdffb65c4f131a013f8152cee24391c1f878 100644 --- a/internal/core/settings/registryhub.go +++ b/internal/core/settings/registryhub.go @@ -33,19 +33,23 @@ func TryLoginRegistry(basicUrl, username, password string, insecure bool) error //get Auth Info auth := resp.Header.Get("Www-Authenticate") - if strings.HasPrefix(auth, "Basic") { + + if strings.EqualFold("Basic", auth[:5]) { authBaseUrl = url queryParams = nil - } else if strings.HasPrefix(auth, "Bearer") { + } else if strings.EqualFold("Bearer", auth[:6]) { //Bearer realm="https://dockerauth.cn-hangzhou.aliyuncs.com/auth",service="registry.aliyuncs.com:cn-hangzhou:26842" - kvArr := strings.Split(strings.TrimPrefix(auth, "Bearer "), ",") + //Bearer realm="https://auth.pkg.coding.net/artifacts-auth/docker/jwt?host=leafly-docker.pkg.coding.net",service="docker" + kvArr := strings.Split(auth[7:], ",") for _, i2 := range kvArr { - temp := strings.Split(i2, "=") - if strings.HasPrefix(i2, "realm") { - authBaseUrl = strings.Trim(temp[1], "\"") + index := strings.Index(i2, "=") + if index == -1 { + continue + } else if strings.EqualFold(strings.Trim(i2[:index], " "), "realm") { + authBaseUrl = strings.Trim(i2[index+1:], "\"") } else { - queryParams = append(queryParams, temp[0]+"="+strings.Trim(temp[1], "\"")) + queryParams = append(queryParams, i2[:index]+"="+strings.Trim(i2[index+1:], "\"")) } } } else { diff --git a/internal/core/settings/registryhub_test.go b/internal/core/settings/registryhub_test.go new file mode 100644 index 0000000000000000000000000000000000000000..9d4aa08831b4e46303d0936b5eac7eba2d4d4fed --- /dev/null +++ b/internal/core/settings/registryhub_test.go @@ -0,0 +1,76 @@ +package settings + +import ( + "fmt" + "github.com/jarcoal/httpmock" + "net/http" + "testing" +) + +func TestTryLoginRegistry(t *testing.T) { + type args struct { + basicUrl string + username string + password string + insecure bool + authHead string + } + tests := []struct { + name string + args args + wantErr bool + }{ + // TODO: Add test cases. + {name: "basic auth pass", args: args{ + basicUrl: "www.unitest.com", + username: "abc", + password: "def", + insecure: false, + authHead: "Basic realm=Nexus Docker Registry", + }, wantErr: false}, + {name: "basic upper auth pass", args: args{ + basicUrl: "www.unitest.com", + username: "abc", + password: "def", + insecure: false, + authHead: "BASIC realm=Nexus Docker Registry", + }, wantErr: false}, + {name: "bearer auth pass", args: args{ + basicUrl: "www.unitest.com", + username: "abc", + password: "def", + insecure: false, + authHead: `Bearer realm=https://beaer.unitest.com,service="registry.unitest.com"`, + }, wantErr: false}, + {name: "bearer complex auth pass", args: args{ + basicUrl: "www.unitest.com", + username: "abc", + password: "def", + insecure: false, + authHead: `Bearer realm=https://beaer.unitest.com/auth?tartget=https://abc.def.com,service="registry.unitest.com"`, + }, wantErr: false}, + } + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + for _, tt := range tests { + httpmock.RegisterResponder("GET", "https://"+tt.args.basicUrl, httpmock.NewStringResponder(200, "ok")) + httpmock.RegisterResponder("GET", fmt.Sprintf("https://%s/v2/", tt.args.basicUrl), + func(req *http.Request) (*http.Response, error) { + if req.Header.Get("Authorization") != "" { + return httpmock.NewStringResponse(200, ""), nil + } + resp := httpmock.NewStringResponse(401, "") + resp.Header.Add("Www-Authenticate", tt.args.authHead) + return resp, nil + }, + ) + httpmock.RegisterResponder("GET", `=~https://beaer\.unitest\.com.*`, httpmock.NewStringResponder(200, "ok")) + t.Run(tt.name, func(t *testing.T) { + if err := TryLoginRegistry(tt.args.basicUrl, tt.args.username, tt.args.password, tt.args.insecure); (err != nil) != tt.wantErr { + t.Errorf("TryLoginRegistry() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +}