diff --git a/examples/config-metrics.json b/examples/config-metrics.json index 7ec5845c16..2b94e25835 100644 --- a/examples/config-metrics.json +++ b/examples/config-metrics.json @@ -5,7 +5,12 @@ }, "http": { "address": "127.0.0.1", - "port": "8080" + "port": "8080", + "auth": { + "htpasswd": { + "path": "test/data/htpasswd" + } + } }, "log": { "level": "debug" diff --git a/pkg/api/authn.go b/pkg/api/authn.go index 8a8b428496..675c1fc1d0 100644 --- a/pkg/api/authn.go +++ b/pkg/api/authn.go @@ -60,7 +60,7 @@ func AuthHandler(ctlr *Controller) mux.MiddlewareFunc { return bearerAuthHandler(ctlr) } - return authnMiddleware.TryAuthnHandlers(ctlr) + return authnMiddleware.tryAuthnHandlers(ctlr) } func (amw *AuthnMiddleware) sessionAuthn(ctlr *Controller, userAc *reqCtx.UserAccessControl, @@ -250,7 +250,7 @@ func (amw *AuthnMiddleware) basicAuthn(ctlr *Controller, userAc *reqCtx.UserAcce return false, nil } -func (amw *AuthnMiddleware) TryAuthnHandlers(ctlr *Controller) mux.MiddlewareFunc { //nolint: gocyclo +func (amw *AuthnMiddleware) tryAuthnHandlers(ctlr *Controller) mux.MiddlewareFunc { //nolint: gocyclo // no password based authN, if neither LDAP nor HTTP BASIC is enabled if !ctlr.Config.IsBasicAuthnEnabled() { return noPasswdAuth(ctlr) diff --git a/pkg/api/authz.go b/pkg/api/authz.go index 3228e8b038..42c972478b 100644 --- a/pkg/api/authz.go +++ b/pkg/api/authz.go @@ -191,14 +191,10 @@ func (ac *AccessController) getAuthnMiddlewareContext(authnType string, request func (ac *AccessController) isPermitted(userGroups []string, username, action string, policyGroup config.PolicyGroup, ) bool { - var result bool - // check repo/system based policies for _, p := range policyGroup.Policies { if common.Contains(p.Users, username) && common.Contains(p.Actions, action) { - result = true - - return result + return true } } @@ -207,9 +203,7 @@ func (ac *AccessController) isPermitted(userGroups []string, username, action st if common.Contains(p.Actions, action) { for _, group := range p.Groups { if common.Contains(userGroups, group) { - result = true - - return result + return true } } } @@ -217,20 +211,16 @@ func (ac *AccessController) isPermitted(userGroups []string, username, action st } // check defaultPolicy - if !result { - if common.Contains(policyGroup.DefaultPolicy, action) && username != "" { - result = true - } + if common.Contains(policyGroup.DefaultPolicy, action) && username != "" { + return true } // check anonymousPolicy - if !result { - if common.Contains(policyGroup.AnonymousPolicy, action) && username == "" { - result = true - } + if common.Contains(policyGroup.AnonymousPolicy, action) && username == "" { + return true } - return result + return false } func BaseAuthzHandler(ctlr *Controller) mux.MiddlewareFunc { @@ -343,3 +333,40 @@ func DistSpecAuthzHandler(ctlr *Controller) mux.MiddlewareFunc { }) } } + +func MetricsAuthzHandler(ctlr *Controller) mux.MiddlewareFunc { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) { + if ctlr.Config.HTTP.AccessControl == nil { + // allow access to authenticated user as anonymous policy does not exist + next.ServeHTTP(response, request) + + return + } + if len(ctlr.Config.HTTP.AccessControl.Metrics.Users) == 0 { + log := ctlr.Log + log.Warn().Msg("auth is enabled but no metrics users in accessControl: /metrics is unaccesible") + common.AuthzFail(response, request, "", ctlr.Config.HTTP.Realm, ctlr.Config.HTTP.Auth.FailDelay) + + return + } + + // get access control context made in authn.go + userAc, err := reqCtx.UserAcFromContext(request.Context()) + if err != nil { // should never happen + common.AuthzFail(response, request, "", ctlr.Config.HTTP.Realm, ctlr.Config.HTTP.Auth.FailDelay) + + return + } + + username := userAc.GetUsername() + if !common.Contains(ctlr.Config.HTTP.AccessControl.Metrics.Users, username) { + common.AuthzFail(response, request, username, ctlr.Config.HTTP.Realm, ctlr.Config.HTTP.Auth.FailDelay) + + return + } + + next.ServeHTTP(response, request) //nolint:contextcheck + }) + } +} diff --git a/pkg/api/config/config.go b/pkg/api/config/config.go index 8ab156e328..c6ed53da26 100644 --- a/pkg/api/config/config.go +++ b/pkg/api/config/config.go @@ -131,6 +131,7 @@ type AccessControlConfig struct { Repositories Repositories `json:"repositories" mapstructure:"repositories"` AdminPolicy Policy Groups Groups + Metrics Metrics } func (config *AccessControlConfig) AnonymousPolicyExists() bool { @@ -168,6 +169,10 @@ type Policy struct { Groups []string } +type Metrics struct { + Users []string +} + type Config struct { DistSpecVersion string `json:"distSpecVersion" mapstructure:"distSpecVersion"` GoVersion string diff --git a/pkg/api/controller_test.go b/pkg/api/controller_test.go index 0f446eaa91..5bd730e3d2 100644 --- a/pkg/api/controller_test.go +++ b/pkg/api/controller_test.go @@ -46,7 +46,6 @@ import ( . "github.com/smartystreets/goconvey/convey" "github.com/stretchr/testify/assert" "go.etcd.io/bbolt" - "golang.org/x/crypto/bcrypt" "gopkg.in/resty.v1" "zotregistry.io/zot/errors" @@ -73,32 +72,17 @@ import ( ) const ( - username = "test" htpasswdUsername = "htpasswduser" - passphrase = "test" group = "test" repo = "test" ServerCert = "../../test/data/server.cert" ServerKey = "../../test/data/server.key" CACert = "../../test/data/ca.crt" - AuthorizedNamespace = "everyone/isallowed" UnauthorizedNamespace = "fortknox/notallowed" ALICE = "alice" AuthorizationNamespace = "authz/image" - AuthorizationAllRepos = "**" ) -func getCredString(username, password string) string { - hash, err := bcrypt.GenerateFromPassword([]byte(password), 10) - if err != nil { - panic(err) - } - - usernameAndHash := fmt.Sprintf("%s:%s", username, string(hash)) - - return usernameAndHash -} - func TestNew(t *testing.T) { Convey("Make a new controller", t, func() { conf := config.New() @@ -524,8 +508,8 @@ func TestHtpasswdSingleCred(t *testing.T) { singleCredtests := []string{} user := ALICE password := ALICE - singleCredtests = append(singleCredtests, getCredString(user, password)) - singleCredtests = append(singleCredtests, getCredString(user, password)+"\n") + singleCredtests = append(singleCredtests, test.GetCredString(user, password)) + singleCredtests = append(singleCredtests, test.GetCredString(user, password)+"\n") for _, testString := range singleCredtests { func() { @@ -583,7 +567,7 @@ func TestAllowMethodsHeader(t *testing.T) { simpleUser := "simpleUser" simpleUserPassword := "simpleUserPass" - credTests := fmt.Sprintf("%s\n\n", getCredString(simpleUser, simpleUserPassword)) + credTests := fmt.Sprintf("%s\n\n", test.GetCredString(simpleUser, simpleUserPassword)) htpasswdPath := test.MakeHtpasswdFileFromString(credTests) defer os.Remove(htpasswdPath) @@ -661,14 +645,14 @@ func TestHtpasswdTwoCreds(t *testing.T) { password1 := "aliciapassword" user2 := "bob" password2 := "robert" - twoCredTests = append(twoCredTests, getCredString(user1, password1)+"\n"+ - getCredString(user2, password2)) + twoCredTests = append(twoCredTests, test.GetCredString(user1, password1)+"\n"+ + test.GetCredString(user2, password2)) - twoCredTests = append(twoCredTests, getCredString(user1, password1)+"\n"+ - getCredString(user2, password2)+"\n") + twoCredTests = append(twoCredTests, test.GetCredString(user1, password1)+"\n"+ + test.GetCredString(user2, password2)+"\n") - twoCredTests = append(twoCredTests, getCredString(user1, password1)+"\n\n"+ - getCredString(user2, password2)+"\n\n") + twoCredTests = append(twoCredTests, test.GetCredString(user1, password1)+"\n\n"+ + test.GetCredString(user2, password2)+"\n\n") for _, testString := range twoCredTests { func() { @@ -717,7 +701,7 @@ func TestHtpasswdFiveCreds(t *testing.T) { } credString := strings.Builder{} for key, val := range tests { - credString.WriteString(getCredString(key, val) + "\n") + credString.WriteString(test.GetCredString(key, val) + "\n") } func() { @@ -886,11 +870,11 @@ func TestBasicAuth(t *testing.T) { So(err, ShouldBeNil) // with creds, should get expected status code - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL) + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/v2/") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + "/v2/") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) }) @@ -970,7 +954,7 @@ func TestInterruptedBlobUpload(t *testing.T) { //nolint: dupl Convey("Test interrupt PATCH blob upload", func() { - resp, err := client.R().Post(baseURL + "/v2/" + AuthorizedNamespace + "/blobs/uploads/") + resp, err := client.R().Post(baseURL + "/v2/" + test.AuthorizedNamespace + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) @@ -999,7 +983,7 @@ func TestInterruptedBlobUpload(t *testing.T) { // if the blob upload has started then interrupt by running cancel() for { - n, err := ctlr.StoreController.DefaultStore.GetBlobUpload(AuthorizedNamespace, sessionID) + n, err := ctlr.StoreController.DefaultStore.GetBlobUpload(test.AuthorizedNamespace, sessionID) if n > 0 && err == nil { cancel() @@ -1012,7 +996,7 @@ func TestInterruptedBlobUpload(t *testing.T) { // wait for zot to remove blobUpload time.Sleep(1 * time.Second) - resp, err = client.R().Get(baseURL + "/v2/" + AuthorizedNamespace + "/blobs/uploads/" + sessionID) + resp, err = client.R().Get(baseURL + "/v2/" + test.AuthorizedNamespace + "/blobs/uploads/" + sessionID) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) @@ -1020,7 +1004,7 @@ func TestInterruptedBlobUpload(t *testing.T) { //nolint: dupl Convey("Test negative interrupt PATCH blob upload", func() { - resp, err := client.R().Post(baseURL + "/v2/" + AuthorizedNamespace + "/blobs/uploads/") + resp, err := client.R().Post(baseURL + "/v2/" + test.AuthorizedNamespace + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) @@ -1049,10 +1033,10 @@ func TestInterruptedBlobUpload(t *testing.T) { // if the blob upload has started then interrupt by running cancel() for { - n, err := ctlr.StoreController.DefaultStore.GetBlobUpload(AuthorizedNamespace, sessionID) + n, err := ctlr.StoreController.DefaultStore.GetBlobUpload(test.AuthorizedNamespace, sessionID) if n > 0 && err == nil { // cleaning blob uploads, so that zot fails to clean up, +code coverage - err = ctlr.StoreController.DefaultStore.DeleteBlobUpload(AuthorizedNamespace, sessionID) + err = ctlr.StoreController.DefaultStore.DeleteBlobUpload(test.AuthorizedNamespace, sessionID) So(err, ShouldBeNil) cancel() @@ -1065,7 +1049,7 @@ func TestInterruptedBlobUpload(t *testing.T) { // wait for zot to remove blobUpload time.Sleep(1 * time.Second) - resp, err = client.R().Get(baseURL + "/v2/" + AuthorizedNamespace + "/blobs/uploads/" + sessionID) + resp, err = client.R().Get(baseURL + "/v2/" + test.AuthorizedNamespace + "/blobs/uploads/" + sessionID) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) @@ -1073,7 +1057,7 @@ func TestInterruptedBlobUpload(t *testing.T) { //nolint: dupl Convey("Test interrupt PUT blob upload", func() { - resp, err := client.R().Post(baseURL + "/v2/" + AuthorizedNamespace + "/blobs/uploads/") + resp, err := client.R().Post(baseURL + "/v2/" + test.AuthorizedNamespace + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) @@ -1102,7 +1086,7 @@ func TestInterruptedBlobUpload(t *testing.T) { // if the blob upload has started then interrupt by running cancel() for { - n, err := ctlr.StoreController.DefaultStore.GetBlobUpload(AuthorizedNamespace, sessionID) + n, err := ctlr.StoreController.DefaultStore.GetBlobUpload(test.AuthorizedNamespace, sessionID) if n > 0 && err == nil { cancel() @@ -1115,7 +1099,7 @@ func TestInterruptedBlobUpload(t *testing.T) { // wait for zot to try to remove blobUpload time.Sleep(1 * time.Second) - resp, err = client.R().Get(baseURL + "/v2/" + AuthorizedNamespace + "/blobs/uploads/" + sessionID) + resp, err = client.R().Get(baseURL + "/v2/" + test.AuthorizedNamespace + "/blobs/uploads/" + sessionID) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) @@ -1123,7 +1107,7 @@ func TestInterruptedBlobUpload(t *testing.T) { //nolint: dupl Convey("Test negative interrupt PUT blob upload", func() { - resp, err := client.R().Post(baseURL + "/v2/" + AuthorizedNamespace + "/blobs/uploads/") + resp, err := client.R().Post(baseURL + "/v2/" + test.AuthorizedNamespace + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) @@ -1152,10 +1136,10 @@ func TestInterruptedBlobUpload(t *testing.T) { // if the blob upload has started then interrupt by running cancel() for { - n, err := ctlr.StoreController.DefaultStore.GetBlobUpload(AuthorizedNamespace, sessionID) + n, err := ctlr.StoreController.DefaultStore.GetBlobUpload(test.AuthorizedNamespace, sessionID) if n > 0 && err == nil { // cleaning blob uploads, so that zot fails to clean up, +code coverage - err = ctlr.StoreController.DefaultStore.DeleteBlobUpload(AuthorizedNamespace, sessionID) + err = ctlr.StoreController.DefaultStore.DeleteBlobUpload(test.AuthorizedNamespace, sessionID) So(err, ShouldBeNil) cancel() @@ -1168,7 +1152,7 @@ func TestInterruptedBlobUpload(t *testing.T) { // wait for zot to try to remove blobUpload time.Sleep(1 * time.Second) - resp, err = client.R().Get(baseURL + "/v2/" + AuthorizedNamespace + "/blobs/uploads/" + sessionID) + resp, err = client.R().Get(baseURL + "/v2/" + test.AuthorizedNamespace + "/blobs/uploads/" + sessionID) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) @@ -1208,7 +1192,7 @@ func TestMultipleInstance(t *testing.T) { client := resty.New() - tagResponse, err := client.R().SetBasicAuth(username, passphrase). + tagResponse, err := client.R().SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/zot-test/tags/list") So(err, ShouldBeNil) So(tagResponse.StatusCode(), ShouldEqual, http.StatusNotFound) @@ -1247,11 +1231,11 @@ func TestMultipleInstance(t *testing.T) { So(err, ShouldBeNil) // with creds, should get expected status code - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL) + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/v2/") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + "/v2/") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) }) @@ -1310,11 +1294,11 @@ func TestMultipleInstance(t *testing.T) { So(err, ShouldBeNil) // with creds, should get expected status code - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL) + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/v2/") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + "/v2/") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) }) @@ -1369,11 +1353,11 @@ func TestTLSWithBasicAuth(t *testing.T) { So(err, ShouldBeNil) // with creds, should get expected status code - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL) + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL + "/v2/") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL + "/v2/") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) }) @@ -1408,7 +1392,7 @@ func TestTLSWithBasicAuthAllowReadAccess(t *testing.T) { conf.HTTP.AccessControl = &config.AccessControlConfig{ Repositories: config.Repositories{ - AuthorizationAllRepos: config.PolicyGroup{ + test.AuthorizationAllRepos: config.PolicyGroup{ AnonymousPolicy: []string{"read"}, }, }, @@ -1432,11 +1416,11 @@ func TestTLSWithBasicAuthAllowReadAccess(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) // with creds, should get expected status code - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL) + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL + "/v2/") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL + "/v2/") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -1473,7 +1457,7 @@ func TestMutualTLSAuthWithUserPermissions(t *testing.T) { conf.HTTP.AccessControl = &config.AccessControlConfig{ Repositories: config.Repositories{ - AuthorizationAllRepos: config.PolicyGroup{ + test.AuthorizationAllRepos: config.PolicyGroup{ Policies: []config.Policy{ { Users: []string{"*"}, @@ -1495,7 +1479,7 @@ func TestMutualTLSAuthWithUserPermissions(t *testing.T) { So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest) - repoPolicy := conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos] + repoPolicy := conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos] // setup TLS mutual auth cert, err := tls.LoadX509KeyPair("../../test/data/client.cert", "../../test/data/client.key") @@ -1533,7 +1517,7 @@ func TestMutualTLSAuthWithUserPermissions(t *testing.T) { // empty default authorization and give user the permission to create repoPolicy.Policies[0].Actions = append(repoPolicy.Policies[0].Actions, "create") - conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos] = repoPolicy + conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos] = repoPolicy resp, err = resty.R().Post(secureBaseURL + "/v2/repo/blobs/uploads/") So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) @@ -1563,7 +1547,7 @@ func TestMutualTLSAuthWithoutCN(t *testing.T) { conf.HTTP.AccessControl = &config.AccessControlConfig{ Repositories: config.Repositories{ - AuthorizationAllRepos: config.PolicyGroup{ + test.AuthorizationAllRepos: config.PolicyGroup{ Policies: []config.Policy{ { Users: []string{"*"}, @@ -1631,7 +1615,7 @@ func TestTLSMutualAuth(t *testing.T) { So(err, ShouldNotBeNil) // with creds but without certs, should get conn error - _, err = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL) + _, err = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL) So(err, ShouldNotBeNil) // setup TLS mutual auth @@ -1648,12 +1632,12 @@ func TestTLSMutualAuth(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) // with client certs and creds, should get expected status code - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL) + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) // with client certs, creds shouldn't matter - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL + "/v2/") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL + "/v2/") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) }) @@ -1682,7 +1666,7 @@ func TestTLSMutualAuthAllowReadAccess(t *testing.T) { conf.HTTP.AccessControl = &config.AccessControlConfig{ Repositories: config.Repositories{ - AuthorizationAllRepos: config.PolicyGroup{ + test.AuthorizationAllRepos: config.PolicyGroup{ AnonymousPolicy: []string{"read"}, }, }, @@ -1706,7 +1690,7 @@ func TestTLSMutualAuthAllowReadAccess(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) // with creds but without certs, reads are allowed - resp, err = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL + "/v2/") + resp, err = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL + "/v2/") So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -1729,12 +1713,12 @@ func TestTLSMutualAuthAllowReadAccess(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) // with client certs and creds, should get expected status code - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL) + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) // with client certs, creds shouldn't matter - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL + "/v2/") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL + "/v2/") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) }) @@ -1787,7 +1771,7 @@ func TestTLSMutualAndBasicAuth(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest) // with creds but without certs, should succeed - _, err = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL) + _, err = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest) @@ -1806,11 +1790,11 @@ func TestTLSMutualAndBasicAuth(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) // with client certs and creds, should get expected status code - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL) + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL + "/v2/") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL + "/v2/") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) }) @@ -1846,7 +1830,7 @@ func TestTLSMutualAndBasicAuthAllowReadAccess(t *testing.T) { conf.HTTP.AccessControl = &config.AccessControlConfig{ Repositories: config.Repositories{ - AuthorizationAllRepos: config.PolicyGroup{ + test.AuthorizationAllRepos: config.PolicyGroup{ AnonymousPolicy: []string{"read"}, }, }, @@ -1871,7 +1855,7 @@ func TestTLSMutualAndBasicAuthAllowReadAccess(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest) // with creds but without certs, should succeed - _, err = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL) + _, err = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest) @@ -1894,11 +1878,11 @@ func TestTLSMutualAndBasicAuthAllowReadAccess(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) // with client certs and creds, should get expected status code - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL) + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(secureBaseURL + "/v2/") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(secureBaseURL + "/v2/") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) }) @@ -1958,7 +1942,7 @@ func (l *testLDAPServer) Bind(bindDN, bindSimplePw string, conn net.Conn) (vldap } if (bindDN == LDAPBindDN && bindSimplePw == LDAPBindPassword) || - (bindDN == fmt.Sprintf("cn=%s,%s", username, LDAPBaseDN) && bindSimplePw == passphrase) { + (bindDN == fmt.Sprintf("cn=%s,%s", test.Username, LDAPBaseDN) && bindSimplePw == test.Passphrase) { return vldap.LDAPResultSuccess, nil } @@ -1968,12 +1952,12 @@ func (l *testLDAPServer) Bind(bindDN, bindSimplePw string, conn net.Conn) (vldap func (l *testLDAPServer) Search(boundDN string, req vldap.SearchRequest, conn net.Conn, ) (vldap.ServerSearchResult, error) { - check := fmt.Sprintf("(uid=%s)", username) + check := fmt.Sprintf("(uid=%s)", test.Username) if check == req.Filter { return vldap.ServerSearchResult{ Entries: []*vldap.Entry{ { - DN: fmt.Sprintf("cn=%s,%s", username, LDAPBaseDN), + DN: fmt.Sprintf("cn=%s,%s", test.Username, LDAPBaseDN), Attributes: []*vldap.EntryAttribute{ { Name: "memberOf", @@ -2030,16 +2014,16 @@ func TestBasicAuthWithLDAP(t *testing.T) { So(err, ShouldBeNil) // with creds, should get expected status code - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL) + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/v2/") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + "/v2/") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) // missing password - resp, _ = resty.R().SetBasicAuth(username, "").Get(baseURL + "/v2/") + resp, _ = resty.R().SetBasicAuth(test.Username, "").Get(baseURL + "/v2/") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) }) @@ -2076,7 +2060,7 @@ func TestGroupsPermissionsForLDAP(t *testing.T) { conf.HTTP.AccessControl = &config.AccessControlConfig{ Groups: config.Groups{ group: { - Users: []string{username}, + Users: []string{test.Username}, }, }, Repositories: config.Repositories{ @@ -2106,7 +2090,7 @@ func TestGroupsPermissionsForLDAP(t *testing.T) { err = UploadImageWithBasicAuth( img, baseURL, repo, img.DigestStr(), - username, passphrase) + test.Username, test.Passphrase) So(err, ShouldBeNil) }) } @@ -2207,7 +2191,7 @@ func TestBearerAuth(t *testing.T) { So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNoContent) - resp, err = resty.R().Post(baseURL + "/v2/" + AuthorizedNamespace + "/blobs/uploads/") + resp, err = resty.R().Post(baseURL + "/v2/" + test.AuthorizedNamespace + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) @@ -2225,7 +2209,7 @@ func TestBearerAuth(t *testing.T) { resp, err = resty.R(). SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). - Post(baseURL + "/v2/" + AuthorizedNamespace + "/blobs/uploads/") + Post(baseURL + "/v2/" + test.AuthorizedNamespace + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) @@ -2265,7 +2249,7 @@ func TestBearerAuth(t *testing.T) { resp, err = resty.R(). SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). - Get(baseURL + "/v2/" + AuthorizedNamespace + "/tags/list") + Get(baseURL + "/v2/" + test.AuthorizedNamespace + "/tags/list") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) @@ -2283,7 +2267,7 @@ func TestBearerAuth(t *testing.T) { resp, err = resty.R(). SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). - Get(baseURL + "/v2/" + AuthorizedNamespace + "/tags/list") + Get(baseURL + "/v2/" + test.AuthorizedNamespace + "/tags/list") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -2361,7 +2345,7 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) { conf.HTTP.AccessControl = &config.AccessControlConfig{ Repositories: config.Repositories{ - AuthorizationAllRepos: config.PolicyGroup{ + test.AuthorizationAllRepos: config.PolicyGroup{ AnonymousPolicy: []string{"read"}, }, }, @@ -2398,7 +2382,7 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) { So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) - resp, err = resty.R().Post(baseURL + "/v2/" + AuthorizedNamespace + "/blobs/uploads/") + resp, err = resty.R().Post(baseURL + "/v2/" + test.AuthorizedNamespace + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) @@ -2416,7 +2400,7 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) { resp, err = resty.R(). SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). - Post(baseURL + "/v2/" + AuthorizedNamespace + "/blobs/uploads/") + Post(baseURL + "/v2/" + test.AuthorizedNamespace + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) @@ -2456,7 +2440,7 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) { resp, err = resty.R(). SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). - Get(baseURL + "/v2/" + AuthorizedNamespace + "/tags/list") + Get(baseURL + "/v2/" + test.AuthorizedNamespace + "/tags/list") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) @@ -2474,7 +2458,7 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) { resp, err = resty.R(). SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). - Get(baseURL + "/v2/" + AuthorizedNamespace + "/tags/list") + Get(baseURL + "/v2/" + test.AuthorizedNamespace + "/tags/list") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -2721,7 +2705,7 @@ func TestOpenIDMiddleware(t *testing.T) { client := resty.New() // without header should not create session - resp, err := client.R().SetBasicAuth(htpasswdUsername, passphrase).Get(baseURL + "/v2/") + resp, err := client.R().SetBasicAuth(htpasswdUsername, test.Passphrase).Get(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -2732,7 +2716,7 @@ func TestOpenIDMiddleware(t *testing.T) { client.SetHeader(constants.SessionClientHeaderName, constants.SessionClientHeaderValue) - resp, err = client.R().SetBasicAuth(htpasswdUsername, passphrase).Get(baseURL + "/v2/") + resp, err = client.R().SetBasicAuth(htpasswdUsername, test.Passphrase).Get(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -2745,7 +2729,7 @@ func TestOpenIDMiddleware(t *testing.T) { client.SetCookies(resp.Cookies()) // should get same cookie - resp, err = client.R().SetBasicAuth(htpasswdUsername, passphrase).Get(baseURL + "/v2/") + resp, err = client.R().SetBasicAuth(htpasswdUsername, test.Passphrase).Get(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -2755,7 +2739,7 @@ func TestOpenIDMiddleware(t *testing.T) { So(sessionsNo, ShouldEqual, 1) resp, err = client.R(). - SetBasicAuth(htpasswdUsername, passphrase). + SetBasicAuth(htpasswdUsername, test.Passphrase). Get(baseURL + constants.FullMgmt) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -2770,7 +2754,7 @@ func TestOpenIDMiddleware(t *testing.T) { So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) - resp, err = client.R().SetBasicAuth(htpasswdUsername, passphrase).Get(baseURL + "/v2/") + resp, err = client.R().SetBasicAuth(htpasswdUsername, test.Passphrase).Get(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -2850,18 +2834,18 @@ func TestOpenIDMiddleware(t *testing.T) { // first login user // with creds, should get expected status code - resp, err = client.R().SetBasicAuth(htpasswdUsername, passphrase).Get(baseURL) + resp, err = client.R().SetBasicAuth(htpasswdUsername, test.Passphrase).Get(baseURL) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) - resp, err = client.R().SetBasicAuth(htpasswdUsername, passphrase).Get(baseURL + "/v2/") + resp, err = client.R().SetBasicAuth(htpasswdUsername, test.Passphrase).Get(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) resp, err = client.R(). - SetBasicAuth(htpasswdUsername, passphrase). + SetBasicAuth(htpasswdUsername, test.Passphrase). Get(baseURL + constants.FullMgmt) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -2913,18 +2897,18 @@ func TestOpenIDMiddleware(t *testing.T) { // first login user // with creds, should get expected status code - resp, err = client.R().SetBasicAuth(username, passphrase).Get(baseURL) + resp, err = client.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) - resp, err = client.R().SetBasicAuth(username, passphrase).Get(baseURL + "/v2/") + resp, err = client.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) resp, err = client.R(). - SetBasicAuth(username, passphrase). + SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + constants.FullMgmt) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3176,7 +3160,7 @@ func TestAuthnSessionErrors(t *testing.T) { } resp, err := client.R(). - SetBasicAuth(htpasswdUsername, passphrase). + SetBasicAuth(htpasswdUsername, test.Passphrase). Get(baseURL + "/v2/_catalog") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3193,7 +3177,7 @@ func TestAuthnSessionErrors(t *testing.T) { } resp, err := client.R(). - SetBasicAuth(username, passphrase). + SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/_catalog") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3336,7 +3320,7 @@ func TestAuthnSessionErrors(t *testing.T) { // first htpasswd saveSessionLoggedUser() error resp, err := client.R(). - SetBasicAuth(htpasswdUsername, passphrase). + SetBasicAuth(htpasswdUsername, test.Passphrase). Get(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3344,7 +3328,7 @@ func TestAuthnSessionErrors(t *testing.T) { // second ldap saveSessionLoggedUser() error resp, err = client.R(). - SetBasicAuth(username, passphrase). + SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3448,7 +3432,7 @@ func TestAuthnSessionErrors(t *testing.T) { session.ID = invalidSessionID session.IsNew = false session.Values["authStatus"] = false - session.Values["username"] = username + session.Values["test.Username"] = test.Username cookieStore, ok := ctlr.CookieStore.(*sessions.FilesystemStore) So(ok, ShouldBeTrue) @@ -3546,7 +3530,7 @@ func TestAuthnMetaDBErrors(t *testing.T) { } resp, err := client.R(). - SetBasicAuth(username, passphrase). + SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/_catalog") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3610,7 +3594,7 @@ func TestAuthorization(t *testing.T) { } conf.HTTP.AccessControl = &config.AccessControlConfig{ Repositories: config.Repositories{ - AuthorizationAllRepos: config.PolicyGroup{ + test.AuthorizationAllRepos: config.PolicyGroup{ Policies: []config.Policy{ { Users: []string{}, @@ -3702,7 +3686,7 @@ func TestAuthorization(t *testing.T) { defer cm.StopServer() client := resty.New() - client.SetBasicAuth(username, passphrase) + client.SetBasicAuth(test.Username, test.Passphrase) RunAuthorizationTests(t, client, baseURL, conf) }) @@ -3714,7 +3698,7 @@ func TestGetUsername(t *testing.T) { port := test.GetFreePort() baseURL := test.GetBaseURL(port) - htpasswdPath := test.MakeHtpasswdFileFromString(getCredString(username, passphrase)) + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(test.Username, test.Passphrase)) defer os.Remove(htpasswdPath) conf := config.New() @@ -3759,7 +3743,7 @@ func TestGetUsername(t *testing.T) { err = json.Unmarshal(resp.Body(), &e) So(err, ShouldBeNil) - resp, err = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/v2/_catalog") + resp, err = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + "/v2/_catalog") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -4065,7 +4049,7 @@ func TestAuthorizationWithAnonymousPolicyBasicAuthAndSessionHeader(t *testing.T) // Can access /v2 with correct credentials resp, err = resty.R(). - SetBasicAuth(htpasswdUsername, passphrase). + SetBasicAuth(htpasswdUsername, test.Passphrase). Get(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -4099,7 +4083,7 @@ func TestAuthorizationWithAnonymousPolicyBasicAuthAndSessionHeader(t *testing.T) So(err, ShouldBeNil) resp, err = resty.R(). - SetBasicAuth(htpasswdUsername, passphrase). + SetBasicAuth(htpasswdUsername, test.Passphrase). Get(baseURL + "/v2/_catalog") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -4124,7 +4108,7 @@ func TestAuthorizationWithAnonymousPolicyBasicAuthAndSessionHeader(t *testing.T) So(err, ShouldNotBeNil) err = UploadImageWithBasicAuth(img, baseURL, - TestRepo, tagAuth, htpasswdUsername, passphrase) + TestRepo, tagAuth, htpasswdUsername, test.Passphrase) So(err, ShouldNotBeNil) err = UploadImageWithBasicAuth(img, baseURL, @@ -4145,7 +4129,7 @@ func TestAuthorizationWithAnonymousPolicyBasicAuthAndSessionHeader(t *testing.T) So(err, ShouldBeNil) err = UploadImageWithBasicAuth(img, baseURL, - TestRepo, tagAuth, htpasswdUsername, passphrase) + TestRepo, tagAuth, htpasswdUsername, test.Passphrase) So(err, ShouldBeNil) err = UploadImageWithBasicAuth(img, baseURL, @@ -4188,7 +4172,7 @@ func TestAuthorizationWithAnonymousPolicyBasicAuthAndSessionHeader(t *testing.T) }{} resp, err = resty.R(). - SetBasicAuth(htpasswdUsername, passphrase). + SetBasicAuth(htpasswdUsername, test.Passphrase). Get(baseURL + "/v2/_catalog") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -4216,8 +4200,8 @@ func TestAuthorizationWithMultiplePolicies(t *testing.T) { conf := config.New() conf.HTTP.Port = port // have two users: "test" user for user Policy, and "bob" for default policy - htpasswdPath := test.MakeHtpasswdFileFromString(getCredString(username, passphrase) + - "\n" + getCredString("bob", passphrase)) + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(test.Username, test.Passphrase) + + "\n" + test.GetCredString("bob", test.Passphrase)) defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -4228,7 +4212,7 @@ func TestAuthorizationWithMultiplePolicies(t *testing.T) { // config with all policy types, to test that the correct one is applied in each case conf.HTTP.AccessControl = &config.AccessControlConfig{ Repositories: config.Repositories{ - AuthorizationAllRepos: config.PolicyGroup{ + test.AuthorizationAllRepos: config.PolicyGroup{ Policies: []config.Policy{ { Users: []string{}, @@ -4346,10 +4330,10 @@ func TestAuthorizationWithMultiplePolicies(t *testing.T) { defer cm.StopServer() testUserClient := resty.New() - testUserClient.SetBasicAuth(username, passphrase) + testUserClient.SetBasicAuth(test.Username, test.Passphrase) bobUserClient := resty.New() - bobUserClient.SetBasicAuth("bob", passphrase) + bobUserClient.SetBasicAuth("bob", test.Passphrase) RunAuthorizationWithMultiplePoliciesTests(t, testUserClient, bobUserClient, baseURL, conf) }) @@ -4363,7 +4347,7 @@ func TestInvalidCases(t *testing.T) { conf := config.New() conf.HTTP.Port = port - htpasswdPath := test.MakeHtpasswdFileFromString(getCredString(username, passphrase)) + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(test.Username, test.Passphrase)) defer os.Remove(htpasswdPath) @@ -4410,7 +4394,7 @@ func TestInvalidCases(t *testing.T) { params["mount"] = digest postResponse, err := client.R(). - SetBasicAuth(username, passphrase).SetQueryParams(params). + SetBasicAuth(test.Username, test.Passphrase).SetQueryParams(params). Post(fmt.Sprintf("%s/v2/%s/blobs/uploads/", baseURL, name)) So(err, ShouldBeNil) So(postResponse.StatusCode(), ShouldEqual, http.StatusInternalServerError) @@ -4422,8 +4406,8 @@ func TestHTTPReadOnly(t *testing.T) { singleCredtests := []string{} user := ALICE password := ALICE - singleCredtests = append(singleCredtests, getCredString(user, password)) - singleCredtests = append(singleCredtests, getCredString(user, password)+"\n") + singleCredtests = append(singleCredtests, test.GetCredString(user, password)) + singleCredtests = append(singleCredtests, test.GetCredString(user, password)+"\n") port := test.GetFreePort() baseURL := test.GetBaseURL(port) @@ -4435,7 +4419,7 @@ func TestHTTPReadOnly(t *testing.T) { // enable read-only mode conf.HTTP.AccessControl = &config.AccessControlConfig{ Repositories: config.Repositories{ - AuthorizationAllRepos: config.PolicyGroup{ + test.AuthorizationAllRepos: config.PolicyGroup{ DefaultPolicy: []string{"read"}, }, }, @@ -4461,7 +4445,7 @@ func TestHTTPReadOnly(t *testing.T) { // with creds, any modifications should still fail on read-only mode resp, err := resty.R().SetBasicAuth(user, password). - Post(baseURL + "/v2/" + AuthorizedNamespace + "/blobs/uploads/") + Post(baseURL + "/v2/" + test.AuthorizedNamespace + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusForbidden) @@ -4482,7 +4466,7 @@ func TestCrossRepoMount(t *testing.T) { conf := config.New() conf.HTTP.Port = port - htpasswdPath := test.MakeHtpasswdFileFromString(getCredString(username, passphrase)) + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(test.Username, test.Passphrase)) defer os.Remove(htpasswdPath) @@ -4518,7 +4502,7 @@ func TestCrossRepoMount(t *testing.T) { params["from"] = name client := resty.New() - headResponse, err := client.R().SetBasicAuth(username, passphrase). + headResponse, err := client.R().SetBasicAuth(test.Username, test.Passphrase). Head(fmt.Sprintf("%s/v2/%s/blobs/%s", baseURL, name, manifestDigest)) So(err, ShouldBeNil) So(headResponse.StatusCode(), ShouldEqual, http.StatusOK) @@ -4527,7 +4511,7 @@ func TestCrossRepoMount(t *testing.T) { params["mount"] = "sha:" postResponse, err := client.R(). - SetBasicAuth(username, passphrase).SetQueryParams(params). + SetBasicAuth(test.Username, test.Passphrase).SetQueryParams(params). Post(baseURL + "/v2/zot-c-test/blobs/uploads/") So(err, ShouldBeNil) So(postResponse.StatusCode(), ShouldEqual, http.StatusAccepted) @@ -4541,7 +4525,7 @@ func TestCrossRepoMount(t *testing.T) { incorrectParams["from"] = "zot-x-test" postResponse, err = client.R(). - SetBasicAuth(username, passphrase).SetQueryParams(incorrectParams). + SetBasicAuth(test.Username, test.Passphrase).SetQueryParams(incorrectParams). Post(baseURL + "/v2/zot-y-test/blobs/uploads/") So(err, ShouldBeNil) So(postResponse.StatusCode(), ShouldEqual, http.StatusAccepted) @@ -4552,7 +4536,7 @@ func TestCrossRepoMount(t *testing.T) { // This is correct request but it will return 202 because blob is not present in cache. params["mount"] = string(manifestDigest) postResponse, err = client.R(). - SetBasicAuth(username, passphrase).SetQueryParams(params). + SetBasicAuth(test.Username, test.Passphrase).SetQueryParams(params). Post(baseURL + "/v2/zot-c-test/blobs/uploads/") So(err, ShouldBeNil) So(postResponse.StatusCode(), ShouldEqual, http.StatusAccepted) @@ -4561,30 +4545,30 @@ func TestCrossRepoMount(t *testing.T) { // Send same request again postResponse, err = client.R(). - SetBasicAuth(username, passphrase).SetQueryParams(params). + SetBasicAuth(test.Username, test.Passphrase).SetQueryParams(params). Post(baseURL + "/v2/zot-c-test/blobs/uploads/") So(err, ShouldBeNil) So(postResponse.StatusCode(), ShouldEqual, http.StatusAccepted) // Valid requests postResponse, err = client.R(). - SetBasicAuth(username, passphrase).SetQueryParams(params). + SetBasicAuth(test.Username, test.Passphrase).SetQueryParams(params). Post(baseURL + "/v2/zot-d-test/blobs/uploads/") So(err, ShouldBeNil) So(postResponse.StatusCode(), ShouldEqual, http.StatusAccepted) - headResponse, err = client.R().SetBasicAuth(username, passphrase). + headResponse, err = client.R().SetBasicAuth(test.Username, test.Passphrase). Head(fmt.Sprintf("%s/v2/zot-cv-test/blobs/%s", baseURL, manifestDigest)) So(err, ShouldBeNil) So(headResponse.StatusCode(), ShouldEqual, http.StatusNotFound) postResponse, err = client.R(). - SetBasicAuth(username, passphrase).SetQueryParams(params).Post(baseURL + "/v2/zot-c-test/blobs/uploads/") + SetBasicAuth(test.Username, test.Passphrase).SetQueryParams(params).Post(baseURL + "/v2/zot-c-test/blobs/uploads/") So(err, ShouldBeNil) So(postResponse.StatusCode(), ShouldEqual, http.StatusAccepted) postResponse, err = client.R(). - SetBasicAuth(username, passphrase).SetQueryParams(params). + SetBasicAuth(test.Username, test.Passphrase).SetQueryParams(params). Post(baseURL + "/v2/ /blobs/uploads/") So(err, ShouldBeNil) So(postResponse.StatusCode(), ShouldEqual, http.StatusNotFound) @@ -4597,7 +4581,7 @@ func TestCrossRepoMount(t *testing.T) { } postResponse, err = client.R().SetHeader("Content-type", "application/octet-stream"). - SetBasicAuth(username, passphrase).SetQueryParam("digest", "sha256:"+blob). + SetBasicAuth(test.Username, test.Passphrase).SetQueryParam("digest", "sha256:"+blob). SetBody(buf).Post(baseURL + "/v2/zot-d-test/blobs/uploads/") So(err, ShouldBeNil) So(postResponse.StatusCode(), ShouldEqual, http.StatusCreated) @@ -4625,7 +4609,7 @@ func TestCrossRepoMount(t *testing.T) { params["mount"] = string(manifestDigest) postResponse, err = client.R(). - SetBasicAuth(username, passphrase).SetQueryParams(params). + SetBasicAuth(test.Username, test.Passphrase).SetQueryParams(params). Post(baseURL + "/v2/zot-mount-test/blobs/uploads/") So(err, ShouldBeNil) So(postResponse.StatusCode(), ShouldEqual, http.StatusCreated) @@ -4650,7 +4634,7 @@ func TestCrossRepoMount(t *testing.T) { params["mount"] = string(manifestDigest) params["from"] = "zot-mount-test" postResponse, err = client.R(). - SetBasicAuth(username, passphrase).SetQueryParams(params). + SetBasicAuth(test.Username, test.Passphrase).SetQueryParams(params). Post(baseURL + "/v2/zot-mount1-test/blobs/uploads/") So(err, ShouldBeNil) So(postResponse.StatusCode(), ShouldEqual, http.StatusCreated) @@ -4664,7 +4648,7 @@ func TestCrossRepoMount(t *testing.T) { So(os.SameFile(cacheFi, linkFi), ShouldEqual, true) - headResponse, err = client.R().SetBasicAuth(username, passphrase). + headResponse, err = client.R().SetBasicAuth(test.Username, test.Passphrase). Head(fmt.Sprintf("%s/v2/zot-cv-test/blobs/%s", baseURL, manifestDigest)) So(err, ShouldBeNil) So(headResponse.StatusCode(), ShouldEqual, http.StatusOK) @@ -4673,7 +4657,7 @@ func TestCrossRepoMount(t *testing.T) { params = make(map[string]string) params["mount"] = "sha256:" postResponse, err = client.R(). - SetBasicAuth(username, passphrase).SetQueryParams(params). + SetBasicAuth(test.Username, test.Passphrase).SetQueryParams(params). Post(baseURL + "/v2/zot-mount-test/blobs/uploads/") So(err, ShouldBeNil) So(postResponse.StatusCode(), ShouldEqual, http.StatusAccepted) @@ -4681,7 +4665,7 @@ func TestCrossRepoMount(t *testing.T) { params = make(map[string]string) params["from"] = "zot-cve-test" postResponse, err = client.R(). - SetBasicAuth(username, passphrase).SetQueryParams(params). + SetBasicAuth(test.Username, test.Passphrase).SetQueryParams(params). Post(baseURL + "/v2/zot-mount-test/blobs/uploads/") So(err, ShouldBeNil) So(postResponse.StatusCode(), ShouldEqual, http.StatusMethodNotAllowed) @@ -4693,7 +4677,7 @@ func TestCrossRepoMount(t *testing.T) { conf := config.New() conf.HTTP.Port = port - htpasswdPath := test.MakeHtpasswdFileFromString(getCredString(username, passphrase)) + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(test.Username, test.Passphrase)) defer os.Remove(htpasswdPath) @@ -4724,7 +4708,7 @@ func TestCrossRepoMount(t *testing.T) { digest := godigest.FromBytes(image.Layers[0]) name := "zot-c-test" client := resty.New() - headResponse, err := client.R().SetBasicAuth(username, passphrase). + headResponse, err := client.R().SetBasicAuth(test.Username, test.Passphrase). Head(fmt.Sprintf("%s/v2/%s/blobs/%s", baseURL, name, digest)) So(err, ShouldBeNil) So(headResponse.StatusCode(), ShouldEqual, http.StatusNotFound) @@ -4834,7 +4818,7 @@ func TestParallelRequests(t *testing.T) { conf := config.New() conf.HTTP.Port = port - htpasswdPath := test.MakeHtpasswdFileFromString(getCredString(username, passphrase)) + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(test.Username, test.Passphrase)) conf.HTTP.Auth = &config.AuthConfig{ HTPasswd: config.AuthHTPasswd{ @@ -4875,7 +4859,7 @@ func TestParallelRequests(t *testing.T) { t.Parallel() client := resty.New() - tagResponse, err := client.R().SetBasicAuth(username, passphrase). + tagResponse, err := client.R().SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/" + testcase.destImageName + "/tags/list") assert.Equal(t, err, nil, "Error should be nil") assert.NotEqual(t, tagResponse.StatusCode(), http.StatusBadRequest, "bad request") @@ -4883,12 +4867,12 @@ func TestParallelRequests(t *testing.T) { manifestList := getAllManifests(path.Join(testImagesDir, testcase.srcImageName)) for _, manifest := range manifestList { - headResponse, err := client.R().SetBasicAuth(username, passphrase). + headResponse, err := client.R().SetBasicAuth(test.Username, test.Passphrase). Head(baseURL + "/v2/" + testcase.destImageName + "/manifests/" + manifest) assert.Equal(t, err, nil, "Error should be nil") assert.Equal(t, headResponse.StatusCode(), http.StatusNotFound, "response status code should return 404") - getResponse, err := client.R().SetBasicAuth(username, passphrase). + getResponse, err := client.R().SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/" + testcase.destImageName + "/manifests/" + manifest) assert.Equal(t, err, nil, "Error should be nil") assert.Equal(t, getResponse.StatusCode(), http.StatusNotFound, "response status code should return 404") @@ -4899,7 +4883,7 @@ func TestParallelRequests(t *testing.T) { for _, blob := range blobList { // Get request of blob headResponse, err := client.R(). - SetBasicAuth(username, passphrase). + SetBasicAuth(test.Username, test.Passphrase). Head(baseURL + "/v2/" + testcase.destImageName + "/blobs/sha256:" + blob) assert.Equal(t, err, nil, "Should not be nil") @@ -4907,7 +4891,7 @@ func TestParallelRequests(t *testing.T) { "internal server error should not occurred") getResponse, err := client.R(). - SetBasicAuth(username, passphrase). + SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/" + testcase.destImageName + "/blobs/sha256:" + blob) assert.Equal(t, err, nil, "Should not be nil") @@ -4924,7 +4908,7 @@ func TestParallelRequests(t *testing.T) { // Post request of blob postResponse, err := client.R(). SetHeader("Content-type", "application/octet-stream"). - SetBasicAuth(username, passphrase). + SetBasicAuth(test.Username, test.Passphrase). SetBody(buf).Post(baseURL + "/v2/" + testcase.destImageName + "/blobs/uploads/") assert.Equal(t, err, nil, "Error should be nil") @@ -4935,7 +4919,7 @@ func TestParallelRequests(t *testing.T) { if run%2 == 0 { postResponse, err = client.R(). SetHeader("Content-type", "application/octet-stream"). - SetBasicAuth(username, passphrase). + SetBasicAuth(test.Username, test.Passphrase). SetBody(buf). Post(baseURL + "/v2/" + testcase.destImageName + "/blobs/uploads/") @@ -4982,7 +4966,7 @@ func TestParallelRequests(t *testing.T) { SetHeader("Content-Type", "application/octet-stream"). SetHeader("Content-Length", fmt.Sprintf("%d", nbytes)). SetHeader("Content-Range", fmt.Sprintf("%d", readContent)+"-"+fmt.Sprintf("%d", readContent+nbytes-1)). - SetBasicAuth(username, passphrase). + SetBasicAuth(test.Username, test.Passphrase). Patch(baseURL + "/v2/" + testcase.destImageName + "/blobs/uploads/" + sessionID) assert.Equal(t, err, nil, "Error should be nil") @@ -5003,7 +4987,7 @@ func TestParallelRequests(t *testing.T) { // Patch request of blob patchResponse, err := client.R().SetBody(buf[0:nbytes]).SetHeader("Content-type", "application/octet-stream"). - SetBasicAuth(username, passphrase). + SetBasicAuth(test.Username, test.Passphrase). Patch(baseURL + "/v2/" + testcase.destImageName + "/blobs/uploads/" + sessionID) if err != nil { panic(err) @@ -5017,7 +5001,7 @@ func TestParallelRequests(t *testing.T) { } else { postResponse, err = client.R(). SetHeader("Content-type", "application/octet-stream"). - SetBasicAuth(username, passphrase). + SetBasicAuth(test.Username, test.Passphrase). SetBody(buf).SetQueryParam("digest", "sha256:"+blob). Post(baseURL + "/v2/" + testcase.destImageName + "/blobs/uploads/") @@ -5027,26 +5011,26 @@ func TestParallelRequests(t *testing.T) { } headResponse, err = client.R(). - SetBasicAuth(username, passphrase). + SetBasicAuth(test.Username, test.Passphrase). Head(baseURL + "/v2/" + testcase.destImageName + "/blobs/sha256:" + blob) assert.Equal(t, err, nil, "Should not be nil") assert.NotEqual(t, headResponse.StatusCode(), http.StatusInternalServerError, "response should return success code") getResponse, err = client.R(). - SetBasicAuth(username, passphrase). + SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/" + testcase.destImageName + "/blobs/sha256:" + blob) assert.Equal(t, err, nil, "Should not be nil") assert.NotEqual(t, getResponse.StatusCode(), http.StatusInternalServerError, "response should return success code") } - tagResponse, err = client.R().SetBasicAuth(username, passphrase). + tagResponse, err = client.R().SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/" + testcase.destImageName + "/tags/list") assert.Equal(t, err, nil, "Error should be nil") assert.Equal(t, tagResponse.StatusCode(), http.StatusOK, "response status code should return success code") - repoResponse, err := client.R().SetBasicAuth(username, passphrase). + repoResponse, err := client.R().SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + constants.RoutePrefix + constants.ExtCatalogPrefix) assert.Equal(t, err, nil, "Error should be nil") assert.Equal(t, repoResponse.StatusCode(), http.StatusOK, "response status code should return success code") @@ -7173,7 +7157,7 @@ func TestManifestCollision(t *testing.T) { conf.HTTP.AccessControl = &config.AccessControlConfig{ Repositories: config.Repositories{ - AuthorizationAllRepos: config.PolicyGroup{ + test.AuthorizationAllRepos: config.PolicyGroup{ AnonymousPolicy: []string{ constants.ReadPermission, constants.CreatePermission, @@ -7231,9 +7215,9 @@ func TestManifestCollision(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusConflict) // remove detectManifestCollision action from ** (all repos) - repoPolicy := conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos] + repoPolicy := conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos] repoPolicy.AnonymousPolicy = []string{"read", "delete"} - conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos] = repoPolicy + conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos] = repoPolicy resp, err = resty.R().Delete(baseURL + "/v2/index/manifests/" + digest.String()) So(err, ShouldBeNil) @@ -8246,7 +8230,7 @@ func TestSearchRoutes(t *testing.T) { user1 := "test" password1 := "test" - testString1 := getCredString(user1, password1) + testString1 := test.GetCredString(user1, password1) htpasswdPath := test.MakeHtpasswdFileFromString(testString1) defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -8395,7 +8379,7 @@ func TestSearchRoutes(t *testing.T) { user1 := "test1" password1 := "test1" group1 := "testgroup3" - testString1 := getCredString(user1, password1) + testString1 := test.GetCredString(user1, password1) htpasswdPath := test.MakeHtpasswdFileFromString(testString1) defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -8478,7 +8462,7 @@ func TestSearchRoutes(t *testing.T) { password1 := "test2" group1 := "testgroup1" group2 := "secondtestgroup" - testString1 := getCredString(user1, password1) + testString1 := test.GetCredString(user1, password1) htpasswdPath := test.MakeHtpasswdFileFromString(testString1) defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -8546,7 +8530,7 @@ func TestSearchRoutes(t *testing.T) { user1 := "test3" password1 := "test3" group1 := "testgroup" - testString1 := getCredString(user1, password1) + testString1 := test.GetCredString(user1, password1) htpasswdPath := test.MakeHtpasswdFileFromString(testString1) defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -8614,7 +8598,7 @@ func TestSearchRoutes(t *testing.T) { user1 := "test4" password1 := "test4" group1 := "testgroup1" - testString1 := getCredString(user1, password1) + testString1 := test.GetCredString(user1, password1) htpasswdPath := test.MakeHtpasswdFileFromString(testString1) defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -8682,7 +8666,7 @@ func TestSearchRoutes(t *testing.T) { user1 := "test5" password1 := "test5" group1 := "testgroup2" - testString1 := getCredString(user1, password1) + testString1 := test.GetCredString(user1, password1) htpasswdPath := test.MakeHtpasswdFileFromString(testString1) defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -8737,10 +8721,10 @@ func TestSearchRoutes(t *testing.T) { defaultVal := true group1 := group - user1 := username - password1 := passphrase + user1 := test.Username + password1 := test.Passphrase - testString1 := getCredString(user1, password1) + testString1 := test.GetCredString(user1, password1) htpasswdPath := test.MakeHtpasswdFileFromString(testString1) defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -9165,9 +9149,9 @@ func RunAuthorizationWithMultiplePoliciesTests(t *testing.T, userClient *resty.C So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 401) - repoPolicy := conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos] + repoPolicy := conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos] repoPolicy.AnonymousPolicy = append(repoPolicy.AnonymousPolicy, "read") - conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos] = repoPolicy + conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos] = repoPolicy // should have access to /v2/, anonymous policy is applied, "read" allowed resp, err = resty.R().Get(baseURL + "/v2/") @@ -9216,7 +9200,7 @@ func RunAuthorizationWithMultiplePoliciesTests(t *testing.T, userClient *resty.C So(resp.StatusCode(), ShouldEqual, http.StatusForbidden) repoPolicy.DefaultPolicy = append(repoPolicy.DefaultPolicy, "read") - conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos] = repoPolicy + conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos] = repoPolicy // with read permission should get 200, because default policy allows reading now resp, err = userClient.R().Get(baseURL + "/v2/" + AuthorizationNamespace + "/tags/list") @@ -9286,7 +9270,7 @@ func RunAuthorizationWithMultiplePoliciesTests(t *testing.T, userClient *resty.C So(catalog.Repositories, ShouldContain, AuthorizationNamespace) // no policy - conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos] = config.PolicyGroup{} + conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos] = config.PolicyGroup{} // no policies, so no anonymous allowed resp, err = resty.R().Get(baseURL + "/v2/_catalog") @@ -9351,9 +9335,9 @@ func RunAuthorizationTests(t *testing.T, client *resty.Client, baseURL string, c // first let's use global based policies // add test user to global policy with create perm - conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos].Policies[0].Users = append(conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos].Policies[0].Users, "test") //nolint:lll // gofumpt conflicts with lll + conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos].Policies[0].Users = append(conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos].Policies[0].Users, "test") //nolint:lll // gofumpt conflicts with lll - conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos].Policies[0].Actions = append(conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos].Policies[0].Actions, "create") //nolint:lll // gofumpt conflicts with lll + conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos].Policies[0].Actions = append(conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos].Policies[0].Actions, "create") //nolint:lll // gofumpt conflicts with lll // now it should get 202 resp, err = client.R().Post(baseURL + "/v2/" + AuthorizationNamespace + "/blobs/uploads/") @@ -9386,7 +9370,7 @@ func RunAuthorizationTests(t *testing.T, client *resty.Client, baseURL string, c So(resp.StatusCode(), ShouldEqual, http.StatusForbidden) // get tags with read access should get 200 - conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos].Policies[0].Actions = append(conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos].Policies[0].Actions, "read") //nolint:lll // gofumpt conflicts with lll + conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos].Policies[0].Actions = append(conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos].Policies[0].Actions, "read") //nolint:lll // gofumpt conflicts with lll resp, err = client.R().Get(baseURL + "/v2/" + AuthorizationNamespace + "/tags/list") So(err, ShouldBeNil) @@ -9412,7 +9396,7 @@ func RunAuthorizationTests(t *testing.T, client *resty.Client, baseURL string, c So(resp.StatusCode(), ShouldEqual, http.StatusForbidden) // add delete perm on repo - conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos].Policies[0].Actions = append(conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos].Policies[0].Actions, "delete") //nolint:lll // gofumpt conflicts with lll + conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos].Policies[0].Actions = append(conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos].Policies[0].Actions, "delete") //nolint:lll // gofumpt conflicts with lll // delete blob should get 202 resp, err = client.R().Delete(baseURL + "/v2/" + AuthorizationNamespace + "/blobs/" + digest) @@ -9507,10 +9491,10 @@ func RunAuthorizationTests(t *testing.T, client *resty.Client, baseURL string, c So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) // remove permissions on **/* so it will not interfere with zot-test namespace - repoPolicy := conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos] + repoPolicy := conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos] repoPolicy.Policies = []config.Policy{} repoPolicy.DefaultPolicy = []string{} - conf.HTTP.AccessControl.Repositories[AuthorizationAllRepos] = repoPolicy + conf.HTTP.AccessControl.Repositories[test.AuthorizationAllRepos] = repoPolicy // get manifest should get 403, we don't have perm at all on this repo resp, err = client.R().Get(baseURL + "/v2/zot-test/manifests/0.0.1") diff --git a/pkg/api/routes.go b/pkg/api/routes.go index 1db9a8044b..6cd5d9a73b 100644 --- a/pkg/api/routes.go +++ b/pkg/api/routes.go @@ -183,7 +183,7 @@ func (rh *RouteHandler) SetupRoutes() { pprof.SetupPprofRoutes(rh.c.Config, prefixedRouter, authHandler, rh.c.Log) // Preconditions for enabling the actual extension routes are part of extensions themselves - ext.SetupMetricsRoutes(rh.c.Config, rh.c.Router, authHandler, rh.c.Log, rh.c.Metrics) + ext.SetupMetricsRoutes(rh.c.Config, rh.c.Router, authHandler, MetricsAuthzHandler(rh.c), rh.c.Log, rh.c.Metrics) ext.SetupSearchRoutes(rh.c.Config, prefixedRouter, rh.c.StoreController, rh.c.MetaDB, rh.c.CveScanner, rh.c.Log) ext.SetupImageTrustRoutes(rh.c.Config, prefixedRouter, rh.c.MetaDB, rh.c.Log) diff --git a/pkg/cli/client/client_test.go b/pkg/cli/client/client_test.go index 6192d44102..1ad17e7b39 100644 --- a/pkg/cli/client/client_test.go +++ b/pkg/cli/client/client_test.go @@ -25,18 +25,13 @@ import ( ) const ( - BaseURL1 = "http://127.0.0.1:8088" BaseSecureURL1 = "https://127.0.0.1:8088" HOST1 = "127.0.0.1:8088" SecurePort1 = "8088" - BaseURL2 = "http://127.0.0.1:8089" BaseSecureURL2 = "https://127.0.0.1:8089" SecurePort2 = "8089" - BaseURL3 = "http://127.0.0.1:8090" BaseSecureURL3 = "https://127.0.0.1:8090" SecurePort3 = "8090" - username = "test" - passphrase = "test" ServerCert = "../../../test/data/server.cert" ServerKey = "../../../test/data/server.key" CACert = "../../../test/data/ca.crt" @@ -116,7 +111,7 @@ func TestTLSWithAuth(t *testing.T) { So(err, ShouldNotBeNil) So(imageBuff.String(), ShouldContainSubstring, "check credentials") - user := fmt.Sprintf("%s:%s", username, passphrase) + user := fmt.Sprintf("%s:%s", test.Username, test.Passphrase) args = []string{"-u", user, "--config", "imagetest"} configPath = makeConfigFile( fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`, diff --git a/pkg/debug/pprof/pprof_test.go b/pkg/debug/pprof/pprof_test.go index f1ceb6c9a5..995569579f 100644 --- a/pkg/debug/pprof/pprof_test.go +++ b/pkg/debug/pprof/pprof_test.go @@ -24,9 +24,9 @@ func TestProfilingAuthz(t *testing.T) { baseURL := test.GetBaseURL(port) adminUsername := "admin" adminPassword := "admin" - username := "test" - password := "test" - authorizationAllRepos := "**" + username := test.Username + password := test.Passphrase + authorizationAllRepos := test.AuthorizationAllRepos testCreds := test.GetCredString(adminUsername, adminPassword) + "\n" + test.GetCredString(username, password) diff --git a/pkg/extensions/README.md b/pkg/extensions/README.md index a6cb9ba33a..6f9df76ba3 100644 --- a/pkg/extensions/README.md +++ b/pkg/extensions/README.md @@ -30,9 +30,9 @@ package extensions IsAdmin bool Username string Groups []string - } + } ``` - This data can then be accessed from the request context so that every extension can apply its own authorization logic, if needed . + This data can then be accessed from the request context so that every extension can apply its own authorization logic, if needed . - when a new extension comes out, the developer should also write some blackbox tests, where a binary that contains the new extension should be tested in a real usage scenario. See [test/blackbox](test/blackbox/sync.bats) folder for multiple extensions examples. @@ -40,6 +40,6 @@ package extensions - with every new extension, you should modify the EXTENSIONS variable in Makefile by adding the new extension. The EXTENSIONS variable represents all extensions and is used in Make targets that require them all (e.g make test). -- the available extensions that can be used at the moment are: sync, scrub, metrics, search . +- the available extensions that can be used at the moment are: sync, search, scrub, metrics, lint, ui, mgmt, userprefs, imagetrust . NOTE: When multiple extensions are used, they should be listed in the above presented order. diff --git a/pkg/extensions/extension_metrics.go b/pkg/extensions/extension_metrics.go index 54e71982fa..1837d7ef78 100644 --- a/pkg/extensions/extension_metrics.go +++ b/pkg/extensions/extension_metrics.go @@ -26,13 +26,14 @@ func EnableMetricsExtension(config *config.Config, log log.Logger, rootDir strin } func SetupMetricsRoutes(config *config.Config, router *mux.Router, - authFunc mux.MiddlewareFunc, log log.Logger, metrics monitoring.MetricServer, + authnFunc, authzFunc mux.MiddlewareFunc, log log.Logger, metrics monitoring.MetricServer, ) { log.Info().Msg("setting up metrics routes") if config.IsMetricsEnabled() { extRouter := router.PathPrefix(config.Extensions.Metrics.Prometheus.Path).Subrouter() - extRouter.Use(authFunc) + extRouter.Use(authnFunc) + extRouter.Use(authzFunc) extRouter.Methods("GET").Handler(promhttp.Handler()) } } diff --git a/pkg/extensions/extension_metrics_disabled.go b/pkg/extensions/extension_metrics_disabled.go index 6d280b9ba6..624fc06125 100644 --- a/pkg/extensions/extension_metrics_disabled.go +++ b/pkg/extensions/extension_metrics_disabled.go @@ -22,13 +22,14 @@ func EnableMetricsExtension(config *config.Config, log log.Logger, rootDir strin // SetupMetricsRoutes ... func SetupMetricsRoutes(conf *config.Config, router *mux.Router, - authFunc mux.MiddlewareFunc, log log.Logger, metrics monitoring.MetricServer, + authnFunc, authzFunc mux.MiddlewareFunc, log log.Logger, metrics monitoring.MetricServer, ) { getMetrics := func(w http.ResponseWriter, r *http.Request) { m := metrics.ReceiveMetrics() zcommon.WriteJSON(w, http.StatusOK, m) } - router.Use(authFunc) + router.Use(authnFunc) + router.Use(authzFunc) router.HandleFunc("/metrics", getMetrics).Methods("GET") } diff --git a/pkg/extensions/lint/lint_test.go b/pkg/extensions/lint/lint_test.go index 9a784bf570..47fdd380d3 100644 --- a/pkg/extensions/lint/lint_test.go +++ b/pkg/extensions/lint/lint_test.go @@ -28,19 +28,6 @@ import ( ociutils "zotregistry.io/zot/pkg/test/oci-utils" ) -const ( - username = "test" - passphrase = "test" - ServerCert = "../../test/data/server.cert" - ServerKey = "../../test/data/server.key" - CACert = "../../test/data/ca.crt" - AuthorizedNamespace = "everyone/isallowed" - UnauthorizedNamespace = "fortknox/notallowed" - ALICE = "alice" - AuthorizationNamespace = "authz/image" - AuthorizationAllRepos = "**" -) - func TestVerifyMandatoryAnnotations(t *testing.T) { //nolint: dupl Convey("Mandatory annotations disabled", t, func() { @@ -67,7 +54,7 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { cm.StartAndWait(port) defer cm.StopServer() - resp, err := resty.R().SetBasicAuth(username, passphrase). + resp, err := resty.R().SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/zot-test/manifests/0.0.1") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -114,7 +101,7 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { cm.StartAndWait(port) defer cm.StopServer() - resp, err := resty.R().SetBasicAuth(username, passphrase). + resp, err := resty.R().SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/zot-test/manifests/0.0.1") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -161,7 +148,7 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { cm.StartAndWait(port) defer cm.StopServer() - resp, err := resty.R().SetBasicAuth(username, passphrase). + resp, err := resty.R().SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/zot-test/manifests/0.0.1") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -214,7 +201,7 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { cm.StartAndWait(port) defer cm.StopServer() - resp, err := resty.R().SetBasicAuth(username, passphrase). + resp, err := resty.R().SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/zot-test/manifests/0.0.1") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -232,7 +219,7 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { configDigest := manifest.Config.Digest - resp, err = resty.R().SetBasicAuth(username, passphrase). + resp, err = resty.R().SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + fmt.Sprintf("/v2/zot-test/blobs/%s", configDigest)) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -302,7 +289,7 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { cm.StartAndWait(port) defer cm.StopServer() - resp, err := resty.R().SetBasicAuth(username, passphrase). + resp, err := resty.R().SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/zot-test/manifests/0.0.1") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -319,7 +306,7 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { configDigest := manifest.Config.Digest - resp, err = resty.R().SetBasicAuth(username, passphrase). + resp, err = resty.R().SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + fmt.Sprintf("/v2/zot-test/blobs/%s", configDigest)) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -389,7 +376,7 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { cm.StartAndWait(port) defer cm.StopServer() - resp, err := resty.R().SetBasicAuth(username, passphrase). + resp, err := resty.R().SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/zot-test/manifests/0.0.1") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -445,7 +432,7 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { cm.StartAndWait(port) defer cm.StopServer() - resp, err := resty.R().SetBasicAuth(username, passphrase). + resp, err := resty.R().SetBasicAuth(test.Username, test.Passphrase). Get(baseURL + "/v2/zot-test/manifests/0.0.1") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) diff --git a/pkg/extensions/monitoring/monitoring_test.go b/pkg/extensions/monitoring/monitoring_test.go index 9b5089f01b..4c2cb78268 100644 --- a/pkg/extensions/monitoring/monitoring_test.go +++ b/pkg/extensions/monitoring/monitoring_test.go @@ -4,7 +4,9 @@ package monitoring_test import ( + "fmt" "net/http" + "os" "testing" "time" @@ -20,6 +22,11 @@ import ( ociutils "zotregistry.io/zot/pkg/test/oci-utils" ) +const ( + metricsuser = "metrics" + metricspass = "metrics" +) + func TestExtensionMetrics(t *testing.T) { Convey("Make a new controller with explicitly enabled metrics", t, func() { port := test.GetFreePort() @@ -103,3 +110,301 @@ func TestExtensionMetrics(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) }) } + +func TestMetricsAuthentication(t *testing.T) { + Convey("test metrics without authentication and metrics enabled", t, func() { + port := test.GetFreePort() + baseURL := test.GetBaseURL(port) + conf := config.New() + conf.HTTP.Port = port + + ctlr := api.NewController(conf) + ctlr.Config.Storage.RootDirectory = t.TempDir() + + cm := test.NewControllerManager(ctlr) + cm.StartAndWait(port) + defer cm.StopServer() + + // metrics endpoint not available + resp, err := resty.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) + }) + Convey("test metrics without authentication and with metrics enabled", t, func() { + port := test.GetFreePort() + baseURL := test.GetBaseURL(port) + conf := config.New() + conf.HTTP.Port = port + enabled := true + metricsConfig := &extconf.MetricsConfig{ + BaseConfig: extconf.BaseConfig{Enable: &enabled}, + Prometheus: &extconf.PrometheusConfig{Path: "/metrics"}, + } + conf.Extensions = &extconf.ExtensionConfig{ + Metrics: metricsConfig, + } + + ctlr := api.NewController(conf) + ctlr.Config.Storage.RootDirectory = t.TempDir() + + cm := test.NewControllerManager(ctlr) + cm.StartAndWait(port) + defer cm.StopServer() + + // without auth set metrics endpoint is available + resp, err := resty.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + }) + Convey("test metrics with authentication and metrics enabled", t, func() { + port := test.GetFreePort() + baseURL := test.GetBaseURL(port) + conf := config.New() + conf.HTTP.Port = port + + credTests := fmt.Sprintf("%s\n%s\n", test.GetCredString(test.Username, test.Passphrase), + test.GetCredString(metricsuser, metricspass)) + htpasswdPath := test.MakeHtpasswdFileFromString(credTests) + + defer os.Remove(htpasswdPath) + conf.HTTP.Auth = &config.AuthConfig{ + HTPasswd: config.AuthHTPasswd{ + Path: htpasswdPath, + }, + } + + enabled := true + metricsConfig := &extconf.MetricsConfig{ + BaseConfig: extconf.BaseConfig{Enable: &enabled}, + Prometheus: &extconf.PrometheusConfig{Path: "/metrics"}, + } + conf.Extensions = &extconf.ExtensionConfig{ + Metrics: metricsConfig, + } + + ctlr := api.NewController(conf) + ctlr.Config.Storage.RootDirectory = t.TempDir() + + cm := test.NewControllerManager(ctlr) + cm.StartAndWait(port) + defer cm.StopServer() + + // without credentials + resp, err := resty.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + + // with wrong credentials + resp, err = resty.R().SetBasicAuth("atacker", "wrongpassword").Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + + // authenticated users + resp, err = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + + resp, err = resty.R().SetBasicAuth(metricsuser, metricspass).Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + }) +} + +func TestMetricsAuthorization(t *testing.T) { + Convey("Make a new controller with auth & metrics enabled", t, func() { + port := test.GetFreePort() + baseURL := test.GetBaseURL(port) + conf := config.New() + conf.HTTP.Port = port + credTests := fmt.Sprintf("%s\n%s\n", test.GetCredString(test.Username, test.Passphrase), + test.GetCredString(metricsuser, metricspass)) + htpasswdPath := test.MakeHtpasswdFileFromString(credTests) + defer os.Remove(htpasswdPath) + + conf.HTTP.Auth = &config.AuthConfig{ + HTPasswd: config.AuthHTPasswd{ + Path: htpasswdPath, + }, + } + + enabled := true + metricsConfig := &extconf.MetricsConfig{ + BaseConfig: extconf.BaseConfig{Enable: &enabled}, + Prometheus: &extconf.PrometheusConfig{Path: "/metrics"}, + } + conf.Extensions = &extconf.ExtensionConfig{ + Metrics: metricsConfig, + } + + Convey("with basic auth: no metrics users in accessControl", func() { + conf.HTTP.AccessControl = &config.AccessControlConfig{ + Metrics: config.Metrics{ + Users: []string{}, + }, + } + ctlr := api.NewController(conf) + ctlr.Config.Storage.RootDirectory = t.TempDir() + + cm := test.NewControllerManager(ctlr) + cm.StartAndWait(port) + defer cm.StopServer() + + // authenticated but not authorized user should not have access to/metrics + client := resty.New() + client.SetBasicAuth(test.Username, test.Passphrase) + resp, err := client.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + + // authenticated but not authorized user should not have access to/metrics + client.SetBasicAuth(metricsuser, metricspass) + resp, err = client.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + }) + Convey("with basic auth: metrics users in accessControl", func() { + conf.HTTP.AccessControl = &config.AccessControlConfig{ + Metrics: config.Metrics{ + Users: []string{metricsuser}, + }, + } + ctlr := api.NewController(conf) + ctlr.Config.Storage.RootDirectory = t.TempDir() + + cm := test.NewControllerManager(ctlr) + cm.StartAndWait(port) + defer cm.StopServer() + + // authenticated but not authorized user should not have access to/metrics + client := resty.New() + client.SetBasicAuth(test.Username, test.Passphrase) + resp, err := client.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusForbidden) + + // authenticated & authorized user should have access to/metrics + client.SetBasicAuth(metricsuser, metricspass) + resp, err = client.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + }) + Convey("with basic auth: with anonymousPolicy in accessControl", func() { + conf.HTTP.AccessControl = &config.AccessControlConfig{ + Metrics: config.Metrics{ + Users: []string{metricsuser}, + }, + Repositories: config.Repositories{ + test.AuthorizationAllRepos: config.PolicyGroup{ + Policies: []config.Policy{ + { + Users: []string{}, + Actions: []string{}, + }, + }, + AnonymousPolicy: []string{"read"}, + DefaultPolicy: []string{}, + }, + }, + } + ctlr := api.NewController(conf) + ctlr.Config.Storage.RootDirectory = t.TempDir() + + cm := test.NewControllerManager(ctlr) + cm.StartAndWait(port) + defer cm.StopServer() + + // unauthenticated clients should not have access to /metrics + resp, err := resty.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + + // unauthenticated clients should not have access to /metrics + resp, err = resty.R().SetBasicAuth("hacker", "trywithwrongpass").Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + + // authenticated but not authorized user should not have access to/metrics + client := resty.New() + client.SetBasicAuth(test.Username, test.Passphrase) + resp, err = client.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusForbidden) + + // authenticated & authorized user should have access to/metrics + client.SetBasicAuth(metricsuser, metricspass) + resp, err = client.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + }) + Convey("with basic auth: with adminPolicy in accessControl", func() { + conf.HTTP.AccessControl = &config.AccessControlConfig{ + Metrics: config.Metrics{ + Users: []string{metricsuser}, + }, + Repositories: config.Repositories{ + test.AuthorizationAllRepos: config.PolicyGroup{ + Policies: []config.Policy{ + { + Users: []string{}, + Actions: []string{}, + }, + }, + DefaultPolicy: []string{}, + }, + }, + AdminPolicy: config.Policy{ + Users: []string{"test"}, + Groups: []string{"admins"}, + Actions: []string{"read", "create", "update", "delete"}, + }, + } + ctlr := api.NewController(conf) + ctlr.Config.Storage.RootDirectory = t.TempDir() + + cm := test.NewControllerManager(ctlr) + cm.StartAndWait(port) + defer cm.StopServer() + + // unauthenticated clients should not have access to /metrics + resp, err := resty.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + + // unauthenticated clients should not have access to /metrics + resp, err = resty.R().SetBasicAuth("hacker", "trywithwrongpass").Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + + // authenticated admin user (but not authorized) should not have access to/metrics + client := resty.New() + client.SetBasicAuth(test.Username, test.Passphrase) + resp, err = client.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusForbidden) + + // authenticated & authorized user should have access to/metrics + client.SetBasicAuth(metricsuser, metricspass) + resp, err = client.R().Get(baseURL + "/metrics") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + }) + }) +} diff --git a/pkg/extensions/search/cve/cve_test.go b/pkg/extensions/search/cve/cve_test.go index 32d9059150..165888b755 100644 --- a/pkg/extensions/search/cve/cve_test.go +++ b/pkg/extensions/search/cve/cve_test.go @@ -38,18 +38,13 @@ import ( mTypes "zotregistry.io/zot/pkg/meta/types" "zotregistry.io/zot/pkg/storage" "zotregistry.io/zot/pkg/storage/local" - . "zotregistry.io/zot/pkg/test/common" + test "zotregistry.io/zot/pkg/test/common" "zotregistry.io/zot/pkg/test/deprecated" . "zotregistry.io/zot/pkg/test/image-utils" "zotregistry.io/zot/pkg/test/mocks" ociutils "zotregistry.io/zot/pkg/test/oci-utils" ) -const ( - username = "test" - passphrase = "test" -) - type CveResult struct { ImgList ImgList `json:"data"` Errors []ErrorGQL `json:"errors"` @@ -418,11 +413,11 @@ func TestImageFormat(t *testing.T) { func TestCVESearchDisabled(t *testing.T) { Convey("Test with CVE search disabled", t, func() { - port := GetFreePort() - baseURL := GetBaseURL(port) + port := test.GetFreePort() + baseURL := test.GetBaseURL(port) conf := config.New() conf.HTTP.Port = port - htpasswdPath := MakeHtpasswdFile() + htpasswdPath := test.MakeHtpasswdFile() defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -454,26 +449,26 @@ func TestCVESearchDisabled(t *testing.T) { ctlr := api.NewController(conf) ctlr.Log.Logger = ctlr.Log.Output(writers) - ctrlManager := NewControllerManager(ctlr) + ctrlManager := test.NewControllerManager(ctlr) ctrlManager.StartAndWait(port) // Wait for trivy db to download - found, err := ReadLogFileAndSearchString(logPath, "CVE config not provided, skipping CVE update", 90*time.Second) + found, err := test.ReadLogFileAndSearchString(logPath, "CVE config not provided, skipping CVE update", 90*time.Second) So(err, ShouldBeNil) So(found, ShouldBeTrue) defer ctrlManager.StopServer() - resp, _ := resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + resp, _ := resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") So(string(resp.Body()), ShouldContainSubstring, "search: CVE search is disabled") So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListForCVE(id:\"CVE-201-20482\"){Results{RepoName%20Tag}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListForCVE(id:\"CVE-201-20482\"){Results{RepoName%20Tag}}}") So(string(resp.Body()), ShouldContainSubstring, "search: CVE search is disabled") So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + "randomId" + "\",image:\"zot-test\"){Results{RepoName%20LastUpdated}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + "randomId" + "\",image:\"zot-test\"){Results{RepoName%20LastUpdated}}}") So(resp, ShouldNotBeNil) So(string(resp.Body()), ShouldContainSubstring, "search: CVE search is disabled") So(resp.StatusCode(), ShouldEqual, 200) @@ -483,11 +478,11 @@ func TestCVESearchDisabled(t *testing.T) { func TestCVESearch(t *testing.T) { Convey("Test image vulnerability scanning", t, func() { updateDuration, _ := time.ParseDuration("1h") - port := GetFreePort() - baseURL := GetBaseURL(port) + port := test.GetFreePort() + baseURL := test.GetBaseURL(port) conf := config.New() conf.HTTP.Port = port - htpasswdPath := MakeHtpasswdFile() + htpasswdPath := test.MakeHtpasswdFile() defer os.Remove(htpasswdPath) dbDir, err := testSetup(t) @@ -529,14 +524,14 @@ func TestCVESearch(t *testing.T) { ctlr := api.NewController(conf) ctlr.Log.Logger = ctlr.Log.Output(writers) - ctrlManager := NewControllerManager(ctlr) + ctrlManager := test.NewControllerManager(ctlr) ctrlManager.StartAndWait(port) // trivy db download fail err = os.Mkdir(dbDir+"/_trivy", 0o000) So(err, ShouldBeNil) - found, err := ReadLogFileAndSearchString(logPath, "Error downloading Trivy DB to destination dir", 180*time.Second) + found, err := test.ReadLogFileAndSearchString(logPath, "Error downloading Trivy DB to destination dir", 180*time.Second) So(err, ShouldBeNil) So(found, ShouldBeTrue) @@ -544,7 +539,7 @@ func TestCVESearch(t *testing.T) { So(err, ShouldBeNil) // Wait for trivy db to download - found, err = ReadLogFileAndSearchString(logPath, "DB update completed, next update scheduled", 180*time.Second) + found, err = test.ReadLogFileAndSearchString(logPath, "DB update completed, next update scheduled", 180*time.Second) So(err, ShouldBeNil) So(found, ShouldBeTrue) @@ -567,21 +562,21 @@ func TestCVESearch(t *testing.T) { So(err, ShouldBeNil) // with creds, should get expected status code - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL) + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 404) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/v2/") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + "/v2/") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix) + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 422) var cveResult CveResult contains := false - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") err = json.Unmarshal(resp.Body(), &cveResult) So(err, ShouldBeNil) for _, err := range cveResult.Errors { @@ -592,7 +587,7 @@ func TestCVESearch(t *testing.T) { } So(contains, ShouldBeTrue) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) @@ -602,7 +597,7 @@ func TestCVESearch(t *testing.T) { cveid := cveResult.ImgList.CVEResultForImage.CVEList[0].ID - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-test\"){Results{RepoName%20LastUpdated}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-test\"){Results{RepoName%20LastUpdated}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) @@ -611,7 +606,7 @@ func TestCVESearch(t *testing.T) { So(err, ShouldBeNil) So(len(imgListWithCVEFixed.Images), ShouldEqual, 0) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-cve-test\"){Results{RepoName%20LastUpdated}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-cve-test\"){Results{RepoName%20LastUpdated}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) @@ -619,11 +614,11 @@ func TestCVESearch(t *testing.T) { So(err, ShouldBeNil) So(len(imgListWithCVEFixed.Images), ShouldEqual, 0) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-test\"){Results{RepoName%20LastUpdated}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-test\"){Results{RepoName%20LastUpdated}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"b/zot-squashfs-test:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"b/zot-squashfs-test:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) @@ -632,108 +627,108 @@ func TestCVESearch(t *testing.T) { So(err, ShouldBeNil) So(len(cveSquashFSResult.ImgList.CVEResultForImage.CVEList), ShouldBeZeroValue) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-noindex:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-noindex:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-squashfs-noindex\"){Results{RepoName%20LastUpdated}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-squashfs-noindex\"){Results{RepoName%20LastUpdated}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-invalid-index:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-invalid-index:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-squashfs-invalid-index\"){Results{RepoName%20LastUpdated}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-squashfs-invalid-index\"){Results{RepoName%20LastUpdated}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-noblobs:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-noblobs:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-squashfs-noblob\"){Results{RepoName%20LastUpdated}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-squashfs-noblob\"){Results{RepoName%20LastUpdated}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-squashfs-test\"){Results{RepoName%20LastUpdated}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-squashfs-test\"){Results{RepoName%20LastUpdated}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-invalid-blob:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-invalid-blob:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-squashfs-invalid-blob\"){Results{RepoName%20LastUpdated}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cveid + "\",image:\"zot-squashfs-invalid-blob\"){Results{RepoName%20LastUpdated}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-test\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-test\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"cntos\"){Tag%20CVEList{Id%20Description%20Severity}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"cntos\"){Tag%20CVEList{Id%20Description%20Severity}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListForCVE(id:\"CVE-201-20482\"){Results{RepoName%20Tag}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListForCVE(id:\"CVE-201-20482\"){Results{RepoName%20Tag}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test\"){Tag%20CVEList{Id%20Description}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test\"){Tag%20CVEList{Id%20Description}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){Tag}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){Tag}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Description%20Severity}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Description%20Severity}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Description%20Severity}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Description%20Severity}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Severity}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Severity}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Description}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Description}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Description}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Description}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) // Testing Invalid Search URL - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){Ta%20CVEList{Id%20Description%20Severity}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){Ta%20CVEList{Id%20Description%20Severity}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 422) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListForCVE(tet:\"CVE-2018-20482\"){Results{RepoName%20Tag}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListForCVE(tet:\"CVE-2018-20482\"){Results{RepoName%20Tag}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 422) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageistForCVE(id:\"CVE-2018-20482\"){Results{RepoName%20Tag}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageistForCVE(id:\"CVE-2018-20482\"){Results{RepoName%20Tag}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 422) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListForCVE(id:\"CVE-2018-20482\"){ame%20Tags}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListForCVE(id:\"CVE-2018-20482\"){ame%20Tags}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 422) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(reo:\"zot-test:1.0.0\"){Tag%20CVEList{Id%20Description%20Severity}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(reo:\"zot-test:1.0.0\"){Tag%20CVEList{Id%20Description%20Severity}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 422) - resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListForCVE(id:\"" + cveid + "\"){Results{RepoName%20Tag}}}") + resp, _ = resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + constants.FullSearchPrefix + "?query={ImageListForCVE(id:\"" + cveid + "\"){Results{RepoName%20Tag}}}") So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) }) @@ -1615,8 +1610,8 @@ func TestFixedTags(t *testing.T) { func TestFixedTagsWithIndex(t *testing.T) { Convey("Test fixed tags", t, func() { tempDir := t.TempDir() - port := GetFreePort() - baseURL := GetBaseURL(port) + port := test.GetFreePort() + baseURL := test.GetBaseURL(port) conf := config.New() conf.HTTP.Port = port defaultVal := true @@ -1644,7 +1639,7 @@ func TestFixedTagsWithIndex(t *testing.T) { ctlr := api.NewController(conf) ctlr.Log.Logger = ctlr.Log.Output(writers) - cm := NewControllerManager(ctlr) + cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) defer cm.StopServer() // push index with 2 manifests: one with vulns and one without @@ -1681,7 +1676,7 @@ func TestFixedTagsWithIndex(t *testing.T) { So(err, ShouldBeNil) // Wait for trivy db to download - found, err := ReadLogFileAndSearchString(logPath, "DB update completed, next update scheduled", 180*time.Second) + found, err := test.ReadLogFileAndSearchString(logPath, "DB update completed, next update scheduled", 180*time.Second) So(err, ShouldBeNil) So(found, ShouldBeTrue) diff --git a/pkg/extensions/search/userprefs_test.go b/pkg/extensions/search/userprefs_test.go index 7d0fda85c5..017239826a 100644 --- a/pkg/extensions/search/userprefs_test.go +++ b/pkg/extensions/search/userprefs_test.go @@ -11,7 +11,6 @@ import ( "testing" . "github.com/smartystreets/goconvey/convey" - "golang.org/x/crypto/bcrypt" "gopkg.in/resty.v1" "zotregistry.io/zot/pkg/api" @@ -23,7 +22,7 @@ import ( "zotregistry.io/zot/pkg/log" "zotregistry.io/zot/pkg/storage" "zotregistry.io/zot/pkg/storage/local" - . "zotregistry.io/zot/pkg/test/common" + test "zotregistry.io/zot/pkg/test/common" "zotregistry.io/zot/pkg/test/deprecated" . "zotregistry.io/zot/pkg/test/image-utils" ) @@ -31,8 +30,8 @@ import ( //nolint:dupl func TestUserData(t *testing.T) { Convey("Test user stars and bookmarks", t, func(c C) { - port := GetFreePort() - baseURL := GetBaseURL(port) + port := test.GetFreePort() + baseURL := test.GetBaseURL(port) defaultVal := true accessibleRepo := "accessible-repo" @@ -44,10 +43,10 @@ func TestUserData(t *testing.T) { simpleUser := "test" simpleUserPassword := "test123" - twoCredTests := fmt.Sprintf("%s\n%s\n\n", getCredString(adminUser, adminPassword), - getCredString(simpleUser, simpleUserPassword)) + twoCredTests := fmt.Sprintf("%s\n%s\n\n", test.GetCredString(adminUser, adminPassword), + test.GetCredString(simpleUser, simpleUserPassword)) - htpasswdPath := MakeHtpasswdFileFromString(twoCredTests) + htpasswdPath := test.MakeHtpasswdFileFromString(twoCredTests) defer os.Remove(htpasswdPath) conf := config.New() @@ -94,7 +93,7 @@ func TestUserData(t *testing.T) { ctlr := api.NewController(conf) - ctlrManager := NewControllerManager(ctlr) + ctlrManager := test.NewControllerManager(ctlr) ctlrManager.StartAndWait(port) defer ctlrManager.StopServer() @@ -458,8 +457,8 @@ func TestUserData(t *testing.T) { } func TestChangingRepoState(t *testing.T) { - port := GetFreePort() - baseURL := GetBaseURL(port) + port := test.GetFreePort() + baseURL := test.GetBaseURL(port) defaultVal := true simpleUser := "test" @@ -468,9 +467,9 @@ func TestChangingRepoState(t *testing.T) { forbiddenRepo := "forbidden" accesibleRepo := "accesible" - credTests := fmt.Sprintf("%s\n\n", getCredString(simpleUser, simpleUserPassword)) + credTests := fmt.Sprintf("%s\n\n", test.GetCredString(simpleUser, simpleUserPassword)) - htpasswdPath := MakeHtpasswdFileFromString(credTests) + htpasswdPath := test.MakeHtpasswdFileFromString(credTests) defer os.Remove(htpasswdPath) conf := config.New() @@ -562,7 +561,7 @@ func TestChangingRepoState(t *testing.T) { t.FailNow() } - ctlrManager := NewControllerManager(ctlr) + ctlrManager := test.NewControllerManager(ctlr) ctlrManager.StartAndWait(port) @@ -622,17 +621,17 @@ func TestChangingRepoState(t *testing.T) { func TestGlobalSearchWithUserPrefFiltering(t *testing.T) { Convey("Bookmarks and Stars filtering", t, func() { dir := t.TempDir() - port := GetFreePort() - baseURL := GetBaseURL(port) + port := test.GetFreePort() + baseURL := test.GetBaseURL(port) conf := config.New() conf.HTTP.Port = port conf.Storage.RootDirectory = dir simpleUser := "simpleUser" simpleUserPassword := "simpleUserPass" - credTests := fmt.Sprintf("%s\n\n", getCredString(simpleUser, simpleUserPassword)) + credTests := fmt.Sprintf("%s\n\n", test.GetCredString(simpleUser, simpleUserPassword)) - htpasswdPath := MakeHtpasswdFileFromString(credTests) + htpasswdPath := test.MakeHtpasswdFileFromString(credTests) defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -664,7 +663,7 @@ func TestGlobalSearchWithUserPrefFiltering(t *testing.T) { ctlr := api.NewController(conf) - ctlrManager := NewControllerManager(ctlr) + ctlrManager := test.NewControllerManager(ctlr) ctlrManager.StartAndWait(port) defer ctlrManager.StopServer() @@ -750,8 +749,8 @@ func TestGlobalSearchWithUserPrefFiltering(t *testing.T) { So(foundRepos, ShouldContain, common.RepoSummary{Name: sbRepo, IsStarred: true, IsBookmarked: true}) // Filter by IsStarred = true && IsBookmarked = false - query = `{ - GlobalSearch(query:"repo", filter:{ IsStarred:true, IsBookmarked:false }) { + query = `{ + GlobalSearch(query:"repo", filter:{ IsStarred:true, IsBookmarked:false }) { Repos { Name IsStarred IsBookmarked } } }` @@ -771,8 +770,8 @@ func TestGlobalSearchWithUserPrefFiltering(t *testing.T) { So(foundRepos, ShouldContain, common.RepoSummary{Name: sRepo, IsStarred: true, IsBookmarked: false}) // Filter by IsBookmarked = true - query = `{ - GlobalSearch(query:"repo", filter:{ IsBookmarked:true }) { + query = `{ + GlobalSearch(query:"repo", filter:{ IsBookmarked:true }) { Repos { Name IsStarred IsBookmarked } } }` @@ -793,8 +792,8 @@ func TestGlobalSearchWithUserPrefFiltering(t *testing.T) { So(foundRepos, ShouldContain, common.RepoSummary{Name: sbRepo, IsStarred: true, IsBookmarked: true}) // Filter by IsBookmarked = true && IsStarred = false - query = `{ - GlobalSearch(query:"repo", filter:{ IsBookmarked:true, IsStarred:false }) { + query = `{ + GlobalSearch(query:"repo", filter:{ IsBookmarked:true, IsStarred:false }) { Repos { Name IsStarred IsBookmarked } } }` @@ -818,17 +817,17 @@ func TestGlobalSearchWithUserPrefFiltering(t *testing.T) { func TestExpandedRepoInfoWithUserPrefs(t *testing.T) { Convey("ExpandedRepoInfo with User Prefs", t, func() { dir := t.TempDir() - port := GetFreePort() - baseURL := GetBaseURL(port) + port := test.GetFreePort() + baseURL := test.GetBaseURL(port) conf := config.New() conf.HTTP.Port = port conf.Storage.RootDirectory = dir simpleUser := "simpleUser" simpleUserPassword := "simpleUserPass" - credTests := fmt.Sprintf("%s\n\n", getCredString(simpleUser, simpleUserPassword)) + credTests := fmt.Sprintf("%s\n\n", test.GetCredString(simpleUser, simpleUserPassword)) - htpasswdPath := MakeHtpasswdFileFromString(credTests) + htpasswdPath := test.MakeHtpasswdFileFromString(credTests) defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -860,7 +859,7 @@ func TestExpandedRepoInfoWithUserPrefs(t *testing.T) { ctlr := api.NewController(conf) - ctlrManager := NewControllerManager(ctlr) + ctlrManager := test.NewControllerManager(ctlr) ctlrManager.StartAndWait(port) defer ctlrManager.StopServer() @@ -888,7 +887,7 @@ func TestExpandedRepoInfoWithUserPrefs(t *testing.T) { { ExpandedRepoInfo(repo:"sbrepo"){ Summary { - Name IsStarred IsBookmarked + Name IsStarred IsBookmarked } } }` @@ -923,7 +922,7 @@ func TestExpandedRepoInfoWithUserPrefs(t *testing.T) { { ExpandedRepoInfo(repo:"srepo"){ Summary { - Name IsStarred IsBookmarked + Name IsStarred IsBookmarked } } }` @@ -958,7 +957,7 @@ func TestExpandedRepoInfoWithUserPrefs(t *testing.T) { { ExpandedRepoInfo(repo:"brepo"){ Summary { - Name IsStarred IsBookmarked + Name IsStarred IsBookmarked } } }` @@ -989,7 +988,7 @@ func TestExpandedRepoInfoWithUserPrefs(t *testing.T) { { ExpandedRepoInfo(repo:"repo"){ Summary { - Name IsStarred IsBookmarked + Name IsStarred IsBookmarked } } }` @@ -1017,14 +1016,3 @@ func PutRepoStarURL(repo string) string { func PutRepoBookmarkURL(repo string) string { return fmt.Sprintf("?repo=%s&action=toggleBookmark", repo) } - -func getCredString(username, password string) string { - hash, err := bcrypt.GenerateFromPassword([]byte(password), 10) - if err != nil { - panic(err) - } - - usernameAndHash := fmt.Sprintf("%s:%s", username, string(hash)) - - return usernameAndHash -} diff --git a/pkg/extensions/sync/sync_test.go b/pkg/extensions/sync/sync_test.go index 52b5dcd737..53947fe280 100644 --- a/pkg/extensions/sync/sync_test.go +++ b/pkg/extensions/sync/sync_test.go @@ -2376,7 +2376,8 @@ func TestBasicAuth(t *testing.T) { defer scm.StopServer() registryName := sync.StripRegistryTransport(srcBaseURL) - credentialsFile := makeCredentialsFile(fmt.Sprintf(`{"%s":{"username": "test", "password": "test"}}`, registryName)) + credentialsFile := makeCredentialsFile(fmt.Sprintf(`{"%s":{"username": "%s", "password": "%s"}}`, + registryName, test.Username, test.Passphrase)) var tlsVerify bool @@ -2474,8 +2475,8 @@ func TestBasicAuth(t *testing.T) { registryName := sync.StripRegistryTransport(srcBaseURL) - credentialsFile := makeCredentialsFile(fmt.Sprintf(`{"%s":{"username": "test", "password": "invalid"}}`, - registryName)) + credentialsFile := makeCredentialsFile(fmt.Sprintf(`{"%s":{"username": "%s", "password": "invalid"}}`, + registryName, test.Username)) var tlsVerify bool @@ -2541,8 +2542,8 @@ func TestBasicAuth(t *testing.T) { registryName := sync.StripRegistryTransport(srcBaseURL) - credentialsFile := makeCredentialsFile(fmt.Sprintf(`{"%s":{"username": "test", "password": "test"}}`, - registryName)) + credentialsFile := makeCredentialsFile(fmt.Sprintf(`{"%s":{"username": "%s", "password": "%s"}}`, + registryName, test.Username, test.Passphrase)) err := os.Chmod(credentialsFile, 0o000) So(err, ShouldBeNil) @@ -2614,7 +2615,8 @@ func TestBasicAuth(t *testing.T) { defer scm.StopServer() registryName := sync.StripRegistryTransport(srcBaseURL) - credentialsFile := makeCredentialsFile(fmt.Sprintf(`{"%s":{"username": "test", "password": "test"}}`, registryName)) + credentialsFile := makeCredentialsFile(fmt.Sprintf(`{"%s":{"username": "%s", "password": "%s"}}`, + registryName, test.Username, test.Passphrase)) defaultValue := false syncRegistryConfig := syncconf.RegistryConfig{ diff --git a/pkg/log/log_test.go b/pkg/log/log_test.go index 6a9fa0e32c..8d2c584cdf 100644 --- a/pkg/log/log_test.go +++ b/pkg/log/log_test.go @@ -24,14 +24,7 @@ import ( "zotregistry.io/zot/pkg/api/config" "zotregistry.io/zot/pkg/api/constants" "zotregistry.io/zot/pkg/log" - . "zotregistry.io/zot/pkg/test/common" -) - -const ( - username = "test" - passphrase = "test" - AuthorizedNamespace = "everyone/isallowed" - UnauthorizedNamespace = "fortknox/notallowed" + test "zotregistry.io/zot/pkg/test/common" ) type AuditLog struct { @@ -49,8 +42,8 @@ func TestAuditLogMessages(t *testing.T) { Convey("Make a new controller", t, func() { dir := t.TempDir() - port := GetFreePort() - baseURL := GetBaseURL(port) + port := test.GetFreePort() + baseURL := test.GetBaseURL(port) conf := config.New() outputPath := dir + "/zot.log" @@ -59,7 +52,7 @@ func TestAuditLogMessages(t *testing.T) { conf.HTTP.Port = port - htpasswdPath := MakeHtpasswdFile() + htpasswdPath := test.MakeHtpasswdFile() defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ HTPasswd: config.AuthHTPasswd{ @@ -70,7 +63,7 @@ func TestAuditLogMessages(t *testing.T) { ctlr := api.NewController(conf) ctlr.Config.Storage.RootDirectory = dir - ctlrManager := NewControllerManager(ctlr) + ctlrManager := test.NewControllerManager(ctlr) ctlrManager.StartAndWait(port) defer ctlrManager.StopServer() @@ -83,7 +76,7 @@ func TestAuditLogMessages(t *testing.T) { defer auditFile.Close() Convey("Test GET request", func() { - resp, err := resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/v2/") + resp, err := resty.R().SetBasicAuth(test.Username, test.Passphrase).Get(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -93,8 +86,8 @@ func TestAuditLogMessages(t *testing.T) { }) Convey("Test POST request", func() { - path := "/v2/" + AuthorizedNamespace + "/blobs/uploads/" - resp, err := resty.R().SetBasicAuth(username, passphrase).Post(baseURL + path) + path := "/v2/" + test.AuthorizedNamespace + "/blobs/uploads/" + resp, err := resty.R().SetBasicAuth(test.Username, test.Passphrase).Post(baseURL + path) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) @@ -115,7 +108,7 @@ func TestAuditLogMessages(t *testing.T) { panic(err) } - So(auditLog.Subject, ShouldEqual, username) + So(auditLog.Subject, ShouldEqual, test.Username) So(auditLog.Action, ShouldEqual, http.MethodPost) So(auditLog.Status, ShouldEqual, http.StatusAccepted) So(auditLog.Object, ShouldEqual, path) @@ -124,10 +117,10 @@ func TestAuditLogMessages(t *testing.T) { Convey("Test PUT and DELETE request", func() { // create upload path := "/v2/repo/blobs/uploads/" - resp, err := resty.R().SetBasicAuth(username, passphrase).Post(baseURL + path) + resp, err := resty.R().SetBasicAuth(test.Username, test.Passphrase).Post(baseURL + path) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) - loc := Location(baseURL, resp) + loc := test.Location(baseURL, resp) So(loc, ShouldNotBeEmpty) location := resp.Header().Get("Location") So(location, ShouldNotBeEmpty) @@ -148,7 +141,7 @@ func TestAuditLogMessages(t *testing.T) { panic(err) } - So(auditLog.Subject, ShouldEqual, username) + So(auditLog.Subject, ShouldEqual, test.Username) So(auditLog.Action, ShouldEqual, http.MethodPost) So(auditLog.Status, ShouldEqual, http.StatusAccepted) So(auditLog.Object, ShouldEqual, path) @@ -159,11 +152,11 @@ func TestAuditLogMessages(t *testing.T) { // blob upload resp, err = resty.R().SetQueryParam("digest", digest.String()). - SetBasicAuth(username, passphrase). + SetBasicAuth(test.Username, test.Passphrase). SetHeader("Content-Type", "application/octet-stream").SetBody(content).Put(loc) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusCreated) - blobLoc := Location(baseURL, resp) + blobLoc := test.Location(baseURL, resp) So(blobLoc, ShouldNotBeEmpty) So(resp.Header().Get(constants.DistContentDigestKey), ShouldNotBeEmpty) @@ -182,7 +175,7 @@ func TestAuditLogMessages(t *testing.T) { panic(err) } - So(auditLog.Subject, ShouldEqual, username) + So(auditLog.Subject, ShouldEqual, test.Username) So(auditLog.Action, ShouldEqual, http.MethodPut) So(auditLog.Status, ShouldEqual, http.StatusCreated) @@ -190,7 +183,7 @@ func TestAuditLogMessages(t *testing.T) { So(auditLog.Object, ShouldEqual, putPath) // delete this blob - resp, err = resty.R().SetBasicAuth(username, passphrase).Delete(blobLoc) + resp, err = resty.R().SetBasicAuth(test.Username, test.Passphrase).Delete(blobLoc) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) So(resp.Header().Get("Content-Length"), ShouldEqual, "0") @@ -210,7 +203,7 @@ func TestAuditLogMessages(t *testing.T) { panic(err) } - So(auditLog.Subject, ShouldEqual, username) + So(auditLog.Subject, ShouldEqual, test.Username) So(auditLog.Action, ShouldEqual, http.MethodDelete) So(auditLog.Status, ShouldEqual, http.StatusAccepted) @@ -220,10 +213,10 @@ func TestAuditLogMessages(t *testing.T) { Convey("Test PATCH request", func() { path := "/v2/repo/blobs/uploads/" - resp, err := resty.R().SetBasicAuth(username, passphrase).Post(baseURL + path) + resp, err := resty.R().SetBasicAuth(test.Username, test.Passphrase).Post(baseURL + path) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) - loc := Location(baseURL, resp) + loc := test.Location(baseURL, resp) So(loc, ShouldNotBeEmpty) location := resp.Header().Get("Location") So(location, ShouldNotBeEmpty) @@ -244,7 +237,7 @@ func TestAuditLogMessages(t *testing.T) { panic(err) } - So(auditLog.Subject, ShouldEqual, username) + So(auditLog.Subject, ShouldEqual, test.Username) So(auditLog.Action, ShouldEqual, http.MethodPost) So(auditLog.Status, ShouldEqual, http.StatusAccepted) So(auditLog.Object, ShouldEqual, path) @@ -257,7 +250,7 @@ func TestAuditLogMessages(t *testing.T) { // write a chunk contentRange := fmt.Sprintf("%d-%d", 0, len(chunk)-1) - resp, err = resty.R().SetBasicAuth(username, passphrase). + resp, err = resty.R().SetBasicAuth(test.Username, test.Passphrase). SetHeader("Content-Type", "application/octet-stream"). SetHeader("Content-Range", contentRange).SetBody(chunk).Patch(loc) So(err, ShouldBeNil) @@ -278,7 +271,7 @@ func TestAuditLogMessages(t *testing.T) { panic(err) } - So(auditLog.Subject, ShouldEqual, username) + So(auditLog.Subject, ShouldEqual, test.Username) So(auditLog.Action, ShouldEqual, http.MethodPatch) So(auditLog.Status, ShouldEqual, http.StatusAccepted) diff --git a/pkg/test/common/utils.go b/pkg/test/common/utils.go index 43c6102ae5..05257992e2 100644 --- a/pkg/test/common/utils.go +++ b/pkg/test/common/utils.go @@ -15,9 +15,13 @@ import ( ) const ( - BaseURL = "http://127.0.0.1:%s" - BaseSecureURL = "https://127.0.0.1:%s" - SleepTime = 100 * time.Millisecond + BaseURL = "http://127.0.0.1:%s" + BaseSecureURL = "https://127.0.0.1:%s" + SleepTime = 100 * time.Millisecond + Username = "test" + Passphrase = "test" + AuthorizedNamespace = "everyone/isallowed" + AuthorizationAllRepos = "**" ) type isser interface { diff --git a/pkg/test/skip/skip_test.go b/pkg/test/skip/skip_test.go new file mode 100644 index 0000000000..b266f11cdb --- /dev/null +++ b/pkg/test/skip/skip_test.go @@ -0,0 +1,37 @@ +package skip_test + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + + tskip "zotregistry.io/zot/pkg/test/skip" +) + +// for code coverage. +func TestSkipS3(t *testing.T) { + envName := "S3MOCK_ENDPOINT" + envVal := os.Getenv(envName) + + if len(envVal) > 0 { + defer os.Setenv(envName, envVal) + err := os.Unsetenv(envName) + assert.Equal(t, err, nil, "Error should be nil") + } + + tskip.SkipS3(t) +} + +func TestSkipDynamo(t *testing.T) { + envName := "DYNAMODBMOCK_ENDPOINT" + envVal := os.Getenv(envName) + + if len(envVal) > 0 { + defer os.Setenv(envName, envVal) + err := os.Unsetenv(envName) + assert.Equal(t, err, nil, "Error should be nil") + } + + tskip.SkipDynamo(t) +} diff --git a/test/blackbox/helpers_metrics.bash b/test/blackbox/helpers_metrics.bash index cce55e5b84..4c225568b8 100644 --- a/test/blackbox/helpers_metrics.bash +++ b/test/blackbox/helpers_metrics.bash @@ -1,3 +1,6 @@ +METRICS_USER=observability +METRICS_PASS=MySecreTPa55 + function metrics_route_check () { local servername="http://127.0.0.1:${1}/metrics" status_code=$(curl --write-out '%{http_code}' ${2} --silent --output /dev/null ${servername}) diff --git a/test/blackbox/metrics.bats b/test/blackbox/metrics.bats index 0d392ac2cf..9a39c664dd 100644 --- a/test/blackbox/metrics.bats +++ b/test/blackbox/metrics.bats @@ -32,6 +32,7 @@ function setup_file() { zot_config_file=${BATS_FILE_TMPDIR}/zot_config.json zot_htpasswd_file=${BATS_FILE_TMPDIR}/zot_htpasswd htpasswd -Bbn ${AUTH_USER} ${AUTH_PASS} >> ${zot_htpasswd_file} + htpasswd -Bbn ${METRICS_USER} ${METRICS_PASS} >> ${zot_htpasswd_file} mkdir -p ${zot_root_dir} touch ${zot_log_file} @@ -48,6 +49,20 @@ function setup_file() { "htpasswd": { "path": "${zot_htpasswd_file}" } + }, + "accessControl": { + "metrics":{ + "users": ["${METRICS_USER}"] + }, + "repositories": { + "**": { + "anonymousPolicy": [ + "read", + "create" + ], + "defaultPolicy": ["read"] + } + } } }, "log": { @@ -80,14 +95,20 @@ function teardown_file() { } @test "unauthorized request to metrics" { +# anonymous policy: metrics endpoint should not be available +# 401 - http.StatusUnauthorized run metrics_route_check 8080 "" 401 [ "$status" -eq 0 ] +# user is not in htpasswd run metrics_route_check 8080 "-u unlucky:wrongpass" 401 [ "$status" -eq 0 ] +# proper user/pass tuple from htpasswd, but user not allowed to access metrics +# 403 - http.StatusForbidden + run metrics_route_check 8080 "-u ${AUTH_USER}:${AUTH_PASS}" 403 + [ "$status" -eq 0 ] } @test "authorized request: metrics enabled" { - run metrics_route_check 8080 "-u ${AUTH_USER}:${AUTH_PASS}" 200 + run metrics_route_check 8080 "-u ${METRICS_USER}:${METRICS_PASS}" 200 [ "$status" -eq 0 ] } - diff --git a/test/blackbox/metrics_minimal.bats b/test/blackbox/metrics_minimal.bats index c693f64ec5..352498840f 100644 --- a/test/blackbox/metrics_minimal.bats +++ b/test/blackbox/metrics_minimal.bats @@ -32,6 +32,7 @@ function setup_file() { zot_config_file=${BATS_FILE_TMPDIR}/zot_config.json zot_htpasswd_file=${BATS_FILE_TMPDIR}/zot_htpasswd htpasswd -Bbn ${AUTH_USER} ${AUTH_PASS} >> ${zot_htpasswd_file} + htpasswd -Bbn ${METRICS_USER} ${METRICS_PASS} >> ${zot_htpasswd_file} mkdir -p ${zot_root_dir} touch ${zot_log_file} @@ -48,6 +49,20 @@ function setup_file() { "htpasswd": { "path": "${zot_htpasswd_file}" } + }, + "accessControl": { + "metrics":{ + "users": ["${METRICS_USER}"] + }, + "repositories": { + "**": { + "anonymousPolicy": [ + "read", + "create" + ], + "defaultPolicy": ["read"] + } + } } }, "log": { @@ -72,13 +87,20 @@ function teardown_file() { } @test "unauthorized request to metrics" { +# anonymous policy: metrics endpoint should not be available +# 401 - http.StatusUnauthorized run metrics_route_check 8080 "" 401 [ "$status" -eq 0 ] +# user is not in htpasswd run metrics_route_check 8080 "-u test:wrongpass" 401 [ "$status" -eq 0 ] +# proper user/pass tuple from htpasswd, but user not allowed to access metrics +# 403 - http.StatusForbidden + run metrics_route_check 8080 "-u ${AUTH_USER}:${AUTH_PASS}" 403 + [ "$status" -eq 0 ] } @test "authorized request: metrics enabled" { - run metrics_route_check 8080 "-u ${AUTH_USER}:${AUTH_PASS}" 200 + run metrics_route_check 8080 "-u ${METRICS_USER}:${METRICS_PASS}" 200 [ "$status" -eq 0 ] -} \ No newline at end of file +}