mirror of
https://github.com/project-zot/zot.git
synced 2024-12-30 22:34:13 -05:00
default policy only authorization
unit tests for manifest integrity when updating Signed-off-by: laurentiuNiculae <themelopeus@gmail.com>
This commit is contained in:
parent
e1a1bdff1a
commit
bb95af5b4d
7 changed files with 417 additions and 12 deletions
30
examples/config-default-authz.json
Normal file
30
examples/config-default-authz.json
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"distSpecVersion": "1.0.1",
|
||||
"storage": {
|
||||
"rootDirectory": "/tmp/zot"
|
||||
},
|
||||
"http": {
|
||||
"address": "127.0.0.1",
|
||||
"port": "8080",
|
||||
"realm": "zot",
|
||||
"accessControl": {
|
||||
"**": {
|
||||
"defaultPolicy": ["read", "create"]
|
||||
},
|
||||
"tmp/**": {
|
||||
"defaultPolicy": ["read", "create", "update"]
|
||||
},
|
||||
"infra/**": {
|
||||
"defaultPolicy": ["read"]
|
||||
},
|
||||
"repos2/repo": {
|
||||
"defaultPolicy": ["read"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"log": {
|
||||
"level": "debug"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -180,7 +180,14 @@ func AuthzHandler(ctlr *Controller) mux.MiddlewareFunc {
|
|||
}
|
||||
|
||||
acCtrlr := NewAccessController(ctlr.Config)
|
||||
username := getUsername(request)
|
||||
|
||||
// allow anonymous authz if no authn present and only default policies are present
|
||||
username := ""
|
||||
|
||||
if isAuthnEnabled(ctlr.Config) {
|
||||
username = getUsername(request)
|
||||
}
|
||||
|
||||
ctx := acCtrlr.getContext(username, request)
|
||||
|
||||
// will return only repos on which client is authorized to read
|
||||
|
@ -202,7 +209,7 @@ func AuthzHandler(ctlr *Controller) mux.MiddlewareFunc {
|
|||
if ok {
|
||||
is := ctlr.StoreController.GetImageStore(resource)
|
||||
tags, err := is.GetImageTags(resource)
|
||||
// if repo exists and request's tag doesn't exist yet then action is UPDATE
|
||||
// if repo exists and request's tag exists then action is UPDATE
|
||||
if err == nil && common.Contains(tags, reference) && reference != "latest" {
|
||||
action = UPDATE
|
||||
}
|
||||
|
|
|
@ -142,7 +142,7 @@ func New() *Config {
|
|||
Commit: Commit,
|
||||
BinaryType: BinaryType,
|
||||
Storage: GlobalStorageConfig{GC: true, GCDelay: storage.DefaultGCDelay, Dedupe: true},
|
||||
HTTP: HTTPConfig{Address: "127.0.0.1", Port: "8080"},
|
||||
HTTP: HTTPConfig{Address: "127.0.0.1", Port: "8080", Auth: &AuthConfig{FailDelay: 0}},
|
||||
Log: &LogConfig{Level: "debug"},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2096,6 +2096,9 @@ func TestAuthorizationWithBasicAuth(t *testing.T) {
|
|||
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||||
|
||||
manifestBlob := resp.Body()
|
||||
var manifest ispec.Manifest
|
||||
err = json.Unmarshal(manifestBlob, &manifest)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// put manifest should get 403 without create perm
|
||||
resp, err = resty.R().SetBasicAuth(username, passphrase).SetBody(manifestBlob).
|
||||
|
@ -2116,25 +2119,100 @@ func TestAuthorizationWithBasicAuth(t *testing.T) {
|
|||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||||
|
||||
// create update config and post it.
|
||||
cblob, cdigest := test.GetRandomImageConfig()
|
||||
|
||||
resp, err = resty.R().SetBasicAuth(username, passphrase).
|
||||
Post(baseURL + "/v2/zot-test/blobs/uploads/")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusAccepted)
|
||||
loc = test.Location(baseURL, resp)
|
||||
|
||||
// uploading blob should get 201
|
||||
resp, err = resty.R().SetBasicAuth(username, passphrase).
|
||||
SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))).
|
||||
SetHeader("Content-Type", "application/octet-stream").
|
||||
SetQueryParam("digest", cdigest.String()).
|
||||
SetBody(cblob).
|
||||
Put(loc)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||||
|
||||
// create updated layer and post it
|
||||
updateBlob := []byte("Hello, blob update!")
|
||||
|
||||
resp, err = resty.R().SetBasicAuth(username, passphrase).
|
||||
Post(baseURL + "/v2/zot-test/blobs/uploads/")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusAccepted)
|
||||
loc = test.Location(baseURL, resp)
|
||||
// uploading blob should get 201
|
||||
resp, err = resty.R().SetBasicAuth(username, passphrase).
|
||||
SetHeader("Content-Length", fmt.Sprintf("%d", len(updateBlob))).
|
||||
SetHeader("Content-Type", "application/octet-stream").
|
||||
SetQueryParam("digest", string(godigest.FromBytes(updateBlob))).
|
||||
SetBody(updateBlob).
|
||||
Put(loc)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||||
|
||||
updatedManifest := ispec.Manifest{
|
||||
Config: ispec.Descriptor{
|
||||
MediaType: "application/vnd.oci.image.config.v1+json",
|
||||
Digest: cdigest,
|
||||
Size: int64(len(cblob)),
|
||||
},
|
||||
Layers: []ispec.Descriptor{
|
||||
{
|
||||
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
||||
Digest: godigest.FromBytes(updateBlob),
|
||||
Size: int64(len(updateBlob)),
|
||||
},
|
||||
},
|
||||
}
|
||||
updatedManifest.SchemaVersion = 2
|
||||
updatedManifestBlob, err := json.Marshal(updatedManifest)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// update manifest should get 403 without update perm
|
||||
resp, err = resty.R().SetBasicAuth(username, passphrase).SetBody(manifestBlob).
|
||||
resp, err = resty.R().SetBasicAuth(username, passphrase).SetBody(updatedManifestBlob).
|
||||
Put(baseURL + "/v2/zot-test/manifests/0.0.2")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusForbidden)
|
||||
|
||||
// get the manifest and check if it's the old one
|
||||
resp, err = resty.R().SetBasicAuth(username, passphrase).
|
||||
Get(baseURL + "/v2/zot-test/manifests/0.0.2")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||||
So(resp.Body(), ShouldResemble, manifestBlob)
|
||||
|
||||
// add update perm on repo
|
||||
conf.AccessControl.Repositories["zot-test"].Policies[0].Actions = append(conf.AccessControl.Repositories["zot-test"].Policies[0].Actions, "update") //nolint:lll // gofumpt conflicts with lll
|
||||
|
||||
// update manifest should get 201 with update perm
|
||||
resp, err = resty.R().SetBasicAuth(username, passphrase).
|
||||
SetHeader("Content-type", "application/vnd.oci.image.manifest.v1+json").
|
||||
SetBody(manifestBlob).
|
||||
SetBody(updatedManifestBlob).
|
||||
Put(baseURL + "/v2/zot-test/manifests/0.0.2")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||||
|
||||
// get the manifest and check if it's the new updated one
|
||||
resp, err = resty.R().SetBasicAuth(username, passphrase).
|
||||
Get(baseURL + "/v2/zot-test/manifests/0.0.2")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||||
So(resp.Body(), ShouldResemble, updatedManifestBlob)
|
||||
|
||||
// now use default repo policy
|
||||
conf.AccessControl.Repositories["zot-test"].Policies[0].Actions = []string{}
|
||||
repoPolicy = conf.AccessControl.Repositories["zot-test"]
|
||||
|
@ -2280,6 +2358,200 @@ func TestAuthorizationWithBasicAuth(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAuthorizationWithOnlyDefaultPolicy(t *testing.T) {
|
||||
Convey("Make a new controller", t, func() {
|
||||
const TestRepo = "my-repos/repo"
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.HTTP.Auth = &config.AuthConfig{}
|
||||
conf.AccessControl = &config.AccessControlConfig{
|
||||
Repositories: config.Repositories{
|
||||
TestRepo: config.PolicyGroup{
|
||||
DefaultPolicy: []string{},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctlr := api.NewController(conf)
|
||||
dir := t.TempDir()
|
||||
ctlr.Config.Storage.RootDirectory = dir
|
||||
|
||||
go startServer(ctlr)
|
||||
defer stopServer(ctlr)
|
||||
test.WaitTillServerReady(baseURL)
|
||||
|
||||
blob := []byte("hello, blob!")
|
||||
digest := godigest.FromBytes(blob).String()
|
||||
|
||||
resp, err := resty.R().Get(baseURL + "/v2/")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||||
|
||||
resp, err = resty.R().Get(baseURL + "/v2/_catalog")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||||
var e api.Error
|
||||
err = json.Unmarshal(resp.Body(), &e)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// should get 403 without create
|
||||
resp, err = resty.R().Post(baseURL + "/v2/" + TestRepo + "/blobs/uploads/")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusForbidden)
|
||||
|
||||
if entry, ok := conf.AccessControl.Repositories[TestRepo]; ok {
|
||||
entry.DefaultPolicy = []string{"create", "read"}
|
||||
conf.AccessControl.Repositories[TestRepo] = entry
|
||||
}
|
||||
|
||||
// now it should get 202
|
||||
resp, err = resty.R().SetBasicAuth(username, passphrase).
|
||||
Post(baseURL + "/v2/" + TestRepo + "/blobs/uploads/")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusAccepted)
|
||||
loc := resp.Header().Get("Location")
|
||||
|
||||
// uploading blob should get 201
|
||||
resp, err = resty.R().SetBasicAuth(username, passphrase).
|
||||
SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))).
|
||||
SetHeader("Content-Type", "application/octet-stream").
|
||||
SetQueryParam("digest", digest).
|
||||
SetBody(blob).
|
||||
Put(baseURL + loc)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||||
|
||||
cblob, cdigest := test.GetRandomImageConfig()
|
||||
|
||||
resp, err = resty.R().SetBasicAuth(username, passphrase).
|
||||
Post(baseURL + "/v2/" + TestRepo + "/blobs/uploads/")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusAccepted)
|
||||
loc = test.Location(baseURL, resp)
|
||||
|
||||
// uploading blob should get 201
|
||||
resp, err = resty.R().SetBasicAuth(username, passphrase).
|
||||
SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))).
|
||||
SetHeader("Content-Type", "application/octet-stream").
|
||||
SetQueryParam("digest", cdigest.String()).
|
||||
SetBody(cblob).
|
||||
Put(loc)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||||
|
||||
manifest := ispec.Manifest{
|
||||
Config: ispec.Descriptor{
|
||||
MediaType: "application/vnd.oci.image.config.v1+json",
|
||||
Digest: cdigest,
|
||||
Size: int64(len(cblob)),
|
||||
},
|
||||
Layers: []ispec.Descriptor{
|
||||
{
|
||||
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
||||
Digest: godigest.FromBytes(blob),
|
||||
Size: int64(len(blob)),
|
||||
},
|
||||
},
|
||||
}
|
||||
manifest.SchemaVersion = 2
|
||||
manifestBlob, err := json.Marshal(manifest)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
resp, err = resty.R().
|
||||
SetHeader("Content-type", "application/vnd.oci.image.manifest.v1+json").
|
||||
SetBody(manifestBlob).
|
||||
Put(baseURL + "/v2/" + TestRepo + "/manifests/0.0.2")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||||
|
||||
updateBlob := []byte("Hello, blob update!")
|
||||
|
||||
resp, err = resty.R().
|
||||
Post(baseURL + "/v2/" + TestRepo + "/blobs/uploads/")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusAccepted)
|
||||
loc = test.Location(baseURL, resp)
|
||||
// uploading blob should get 201
|
||||
resp, err = resty.R().
|
||||
SetHeader("Content-Length", fmt.Sprintf("%d", len(updateBlob))).
|
||||
SetHeader("Content-Type", "application/octet-stream").
|
||||
SetQueryParam("digest", string(godigest.FromBytes(updateBlob))).
|
||||
SetBody(updateBlob).
|
||||
Put(loc)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||||
|
||||
updatedManifest := ispec.Manifest{
|
||||
Config: ispec.Descriptor{
|
||||
MediaType: "application/vnd.oci.image.config.v1+json",
|
||||
Digest: cdigest,
|
||||
Size: int64(len(cblob)),
|
||||
},
|
||||
Layers: []ispec.Descriptor{
|
||||
{
|
||||
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
||||
Digest: godigest.FromBytes(updateBlob),
|
||||
Size: int64(len(updateBlob)),
|
||||
},
|
||||
},
|
||||
}
|
||||
updatedManifest.SchemaVersion = 2
|
||||
updatedManifestBlob, err := json.Marshal(updatedManifest)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// update manifest should get 403 without update perm
|
||||
resp, err = resty.R().SetBody(updatedManifestBlob).
|
||||
Put(baseURL + "/v2/" + TestRepo + "/manifests/0.0.2")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusForbidden)
|
||||
|
||||
// get the manifest and check if it's the old one
|
||||
resp, err = resty.R().
|
||||
Get(baseURL + "/v2/" + TestRepo + "/manifests/0.0.2")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||||
So(resp.Body(), ShouldResemble, manifestBlob)
|
||||
|
||||
// add update perm on repo
|
||||
if entry, ok := conf.AccessControl.Repositories[TestRepo]; ok {
|
||||
entry.DefaultPolicy = []string{"create", "read", "update"}
|
||||
conf.AccessControl.Repositories[TestRepo] = entry
|
||||
}
|
||||
|
||||
// update manifest should get 201 with update perm
|
||||
resp, err = resty.R().
|
||||
SetHeader("Content-type", "application/vnd.oci.image.manifest.v1+json").
|
||||
SetBody(updatedManifestBlob).
|
||||
Put(baseURL + "/v2/" + TestRepo + "/manifests/0.0.2")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
|
||||
|
||||
// get the manifest and check if it's the new updated one
|
||||
resp, err = resty.R().
|
||||
Get(baseURL + "/v2/" + TestRepo + "/manifests/0.0.2")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||||
So(resp.Body(), ShouldResemble, updatedManifestBlob)
|
||||
})
|
||||
}
|
||||
|
||||
func TestInvalidCases(t *testing.T) {
|
||||
Convey("Invalid repo dir", t, func() {
|
||||
port := test.GetFreePort()
|
||||
|
|
|
@ -57,9 +57,15 @@ func allowedMethods(method string) []string {
|
|||
// nolint: contextcheck
|
||||
func (rh *RouteHandler) SetupRoutes() {
|
||||
rh.c.Router.Use(AuthHandler(rh.c))
|
||||
// authz is being enabled because authn is found
|
||||
if rh.c.Config.AccessControl != nil && !isBearerAuthEnabled(rh.c.Config) && isAuthnEnabled(rh.c.Config) {
|
||||
// authz is being enabled if AccessControl is specified
|
||||
// if Authn is not present AccessControl will have only default policies
|
||||
if rh.c.Config.AccessControl != nil && !isBearerAuthEnabled(rh.c.Config) {
|
||||
if isAuthnEnabled(rh.c.Config) {
|
||||
rh.c.Log.Info().Msg("access control is being enabled")
|
||||
} else {
|
||||
rh.c.Log.Info().Msg("default policy only access control is being enabled")
|
||||
}
|
||||
|
||||
rh.c.Router.Use(AuthzHandler(rh.c))
|
||||
}
|
||||
|
||||
|
|
|
@ -231,10 +231,8 @@ func validateConfiguration(config *config.Config) error {
|
|||
// check authorization config, it should have basic auth enabled or ldap
|
||||
if config.HTTP.RawAccessControl != nil {
|
||||
if config.HTTP.Auth == nil || (config.HTTP.Auth.HTPasswd.Path == "" && config.HTTP.Auth.LDAP == nil) {
|
||||
log.Error().Err(errors.ErrBadConfig).
|
||||
Msg("access control config requires httpasswd or ldap authentication to be enabled")
|
||||
|
||||
return errors.ErrBadConfig
|
||||
// checking for default policy only authorization config: no users, no policies but default policy
|
||||
checkForDefaultPolicyConfig(config)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,6 +309,15 @@ func validateConfiguration(config *config.Config) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func checkForDefaultPolicyConfig(config *config.Config) {
|
||||
if !isDefaultPolicyConfig(config) {
|
||||
log.Error().Err(errors.ErrBadConfig).
|
||||
Msg("access control config requires httpasswd, ldap authentication " +
|
||||
"or using only 'defaultPolicy' policies")
|
||||
panic(errors.ErrBadConfig)
|
||||
}
|
||||
}
|
||||
|
||||
func applyDefaultValues(config *config.Config, viperInstance *viper.Viper) {
|
||||
defaultVal := true
|
||||
|
||||
|
@ -431,3 +438,30 @@ func LoadConfiguration(config *config.Config, configPath string) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func isDefaultPolicyConfig(cfg *config.Config) bool {
|
||||
adminPolicy := cfg.AccessControl.AdminPolicy
|
||||
|
||||
log.Info().Msg("checking if default authorization is possible")
|
||||
|
||||
if len(adminPolicy.Actions)+len(adminPolicy.Users) > 0 {
|
||||
log.Info().Msg("admin policy detected, default authorization disabled")
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
for _, repository := range cfg.AccessControl.Repositories {
|
||||
for _, policy := range repository.Policies {
|
||||
if len(policy.Actions)+len(policy.Users) > 0 {
|
||||
log.Info().Interface("repository", repository).
|
||||
Msg("repository with non-empty policy detected, default authorization disabled")
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Info().Msg("default authorization detected")
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -174,6 +174,62 @@ func TestVerify(t *testing.T) {
|
|||
So(func() { _ = cli.NewServerRootCmd().Execute() }, ShouldNotPanic)
|
||||
})
|
||||
|
||||
Convey("Test verify default authorization", t, func(c C) {
|
||||
tmpfile, err := ioutil.TempFile("", "zot-test*.json")
|
||||
So(err, ShouldBeNil)
|
||||
defer os.Remove(tmpfile.Name()) // clean up
|
||||
content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"},
|
||||
"http":{"address":"127.0.0.1","port":"8080","realm":"zot",
|
||||
"accessControl":{"**":{"defaultPolicy": ["read", "create"]},
|
||||
"/repo":{"defaultPolicy": ["read", "create"]}
|
||||
}}}`)
|
||||
_, err = tmpfile.Write(content)
|
||||
So(err, ShouldBeNil)
|
||||
err = tmpfile.Close()
|
||||
So(err, ShouldBeNil)
|
||||
os.Args = []string{"cli_test", "verify", tmpfile.Name()}
|
||||
So(func() { _ = cli.NewServerRootCmd().Execute() }, ShouldNotPanic)
|
||||
})
|
||||
|
||||
Convey("Test verify default authorization fail", t, func(c C) {
|
||||
tmpfile, err := ioutil.TempFile("", "zot-test*.json")
|
||||
So(err, ShouldBeNil)
|
||||
defer os.Remove(tmpfile.Name()) // clean up
|
||||
content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"},
|
||||
"http":{"address":"127.0.0.1","port":"8080","realm":"zot",
|
||||
"accessControl":{"**":{"defaultPolicy": ["read", "create"]},
|
||||
"/repo":{"defaultPolicy": ["read", "create"]},
|
||||
"adminPolicy":{"users":["admin"],
|
||||
"actions":["read","create","update","delete"]}
|
||||
}}}`)
|
||||
_, err = tmpfile.Write(content)
|
||||
So(err, ShouldBeNil)
|
||||
err = tmpfile.Close()
|
||||
So(err, ShouldBeNil)
|
||||
os.Args = []string{"cli_test", "verify", tmpfile.Name()}
|
||||
So(func() { _ = cli.NewServerRootCmd().Execute() }, ShouldPanic)
|
||||
})
|
||||
|
||||
Convey("Test verify default authorization fail", t, func(c C) {
|
||||
tmpfile, err := ioutil.TempFile("", "zot-test*.json")
|
||||
So(err, ShouldBeNil)
|
||||
defer os.Remove(tmpfile.Name()) // clean up
|
||||
content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"},
|
||||
"http":{"address":"127.0.0.1","port":"8080","realm":"zot",
|
||||
"accessControl":{"**":{"defaultPolicy": ["read", "create"]},
|
||||
"/repo":{"defaultPolicy": ["read", "create"]},
|
||||
"/repo2":{"policies": [{
|
||||
"users": ["charlie"],
|
||||
"actions": ["read", "create", "update"]}]}
|
||||
}}}`)
|
||||
_, err = tmpfile.Write(content)
|
||||
So(err, ShouldBeNil)
|
||||
err = tmpfile.Close()
|
||||
So(err, ShouldBeNil)
|
||||
os.Args = []string{"cli_test", "verify", tmpfile.Name()}
|
||||
So(func() { _ = cli.NewServerRootCmd().Execute() }, ShouldPanic)
|
||||
})
|
||||
|
||||
Convey("Test verify w/ sync and w/o filesystem storage", t, func(c C) {
|
||||
tmpfile, err := ioutil.TempFile("", "zot-test*.json")
|
||||
So(err, ShouldBeNil)
|
||||
|
|
Loading…
Reference in a new issue