mirror of
https://github.com/project-zot/zot.git
synced 2026-06-17 04:48:26 +08:00
[Identity-based Authorization] Add an option to specify a global policy for all repositories
using regex. Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
This commit is contained in:
committed by
Ramkumar Chinchani
parent
3177f87403
commit
4f825a5e2f
+54
-34
@@ -186,25 +186,7 @@ func NewRootCmd() *cobra.Command {
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
func LoadConfiguration(config *config.Config, configPath string) {
|
||||
viper.SetConfigFile(configPath)
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
log.Error().Err(err).Msg("error while reading configuration")
|
||||
panic(err)
|
||||
}
|
||||
|
||||
metaData := &mapstructure.Metadata{}
|
||||
if err := viper.Unmarshal(&config, metadataConfig(metaData)); err != nil {
|
||||
log.Error().Err(err).Msg("error while unmarshalling new config")
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if len(metaData.Keys) == 0 || len(metaData.Unused) > 0 {
|
||||
log.Error().Err(errors.ErrBadConfig).Msg("bad configuration, retry writing it")
|
||||
panic(errors.ErrBadConfig)
|
||||
}
|
||||
|
||||
func validateConfiguration(config *config.Config) {
|
||||
// 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) {
|
||||
@@ -228,14 +210,14 @@ func LoadConfiguration(config *config.Config, configPath string) {
|
||||
}
|
||||
}
|
||||
|
||||
// check glob patterns in sync are compilable
|
||||
// check glob patterns in sync config are compilable
|
||||
if config.Extensions != nil && config.Extensions.Sync != nil {
|
||||
for _, regCfg := range config.Extensions.Sync.Registries {
|
||||
if regCfg.Content != nil {
|
||||
for _, content := range regCfg.Content {
|
||||
ok := glob.ValidatePattern(content.Prefix)
|
||||
if !ok {
|
||||
log.Error().Err(glob.ErrBadPattern).Str("pattern", content.Prefix).Msg("pattern could not be compiled")
|
||||
log.Error().Err(glob.ErrBadPattern).Str("pattern", content.Prefix).Msg("sync pattern could not be compiled")
|
||||
panic(errors.ErrBadConfig)
|
||||
}
|
||||
}
|
||||
@@ -260,19 +242,57 @@ func LoadConfiguration(config *config.Config, configPath string) {
|
||||
}
|
||||
}
|
||||
|
||||
err := config.LoadAccessControlConfig()
|
||||
if err != nil {
|
||||
log.Error().Err(errors.ErrBadConfig).Msg("unable to unmarshal http.accessControl.key.policies")
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// defaults
|
||||
defualtTLSVerify := true
|
||||
|
||||
if config.Extensions != nil && config.Extensions.Sync != nil {
|
||||
for id, regCfg := range config.Extensions.Sync.Registries {
|
||||
if regCfg.TLSVerify == nil {
|
||||
config.Extensions.Sync.Registries[id].TLSVerify = &defualtTLSVerify
|
||||
// check glob patterns in authz config are compilable
|
||||
if config.AccessControl != nil {
|
||||
for pattern := range config.AccessControl.Repositories {
|
||||
ok := glob.ValidatePattern(pattern)
|
||||
if !ok {
|
||||
log.Error().Err(glob.ErrBadPattern).Str("pattern", pattern).Msg("authorization pattern could not be compiled")
|
||||
panic(errors.ErrBadConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func LoadConfiguration(config *config.Config, configPath string) {
|
||||
// Default is dot (.) but because we allow glob patterns in authz
|
||||
// we need another key delimiter.
|
||||
viperInstance := viper.NewWithOptions(viper.KeyDelimiter("::"))
|
||||
|
||||
viperInstance.SetConfigFile(configPath)
|
||||
|
||||
if err := viperInstance.ReadInConfig(); err != nil {
|
||||
log.Error().Err(err).Msg("error while reading configuration")
|
||||
panic(err)
|
||||
}
|
||||
|
||||
metaData := &mapstructure.Metadata{}
|
||||
if err := viperInstance.Unmarshal(&config, metadataConfig(metaData)); err != nil {
|
||||
log.Error().Err(err).Msg("error while unmarshalling new config")
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if len(metaData.Keys) == 0 || len(metaData.Unused) > 0 {
|
||||
log.Error().Err(errors.ErrBadConfig).Msg("bad configuration, retry writing it")
|
||||
panic(errors.ErrBadConfig)
|
||||
}
|
||||
|
||||
err := config.LoadAccessControlConfig(viperInstance)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("unable to unmarshal config's accessControl")
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// various config checks
|
||||
validateConfiguration(config)
|
||||
|
||||
// defaults
|
||||
defaultTLSVerify := true
|
||||
|
||||
if config.Extensions != nil && config.Extensions.Sync != nil {
|
||||
for id, regCfg := range config.Extensions.Sync.Registries {
|
||||
if regCfg.TLSVerify == nil {
|
||||
config.Extensions.Sync.Registries[id].TLSVerify = &defaultTLSVerify
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+34
-4
@@ -10,7 +10,6 @@ import (
|
||||
"time"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"github.com/spf13/viper"
|
||||
"gopkg.in/resty.v1"
|
||||
"zotregistry.io/zot/pkg/api"
|
||||
"zotregistry.io/zot/pkg/api/config"
|
||||
@@ -188,6 +187,40 @@ func TestVerify(t *testing.T) {
|
||||
So(func() { _ = cli.NewRootCmd().Execute() }, ShouldPanic)
|
||||
})
|
||||
|
||||
Convey("Test verify with bad authorization repo patterns", 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",
|
||||
"auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1},
|
||||
"accessControl":{"\|":{"policies":[],"defaultPolicy":[]}}}}`)
|
||||
_, err = tmpfile.Write(content)
|
||||
So(err, ShouldBeNil)
|
||||
err = tmpfile.Close()
|
||||
So(err, ShouldBeNil)
|
||||
os.Args = []string{"cli_test", "verify", tmpfile.Name()}
|
||||
So(func() { _ = cli.NewRootCmd().Execute() }, ShouldPanic)
|
||||
})
|
||||
|
||||
Convey("Test verify sync config default tls value", 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",
|
||||
"auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}},
|
||||
"extensions":{"sync": {"registries": [{"url":"localhost:9999",
|
||||
"content": [{"prefix":"repo**"}]}]}}}`)
|
||||
_, err = tmpfile.Write(content)
|
||||
So(err, ShouldBeNil)
|
||||
err = tmpfile.Close()
|
||||
So(err, ShouldBeNil)
|
||||
os.Args = []string{"cli_test", "verify", tmpfile.Name()}
|
||||
err = cli.NewRootCmd().Execute()
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("Test verify good config", t, func(c C) {
|
||||
tmpfile, err := ioutil.TempFile("", "zot-test*.json")
|
||||
So(err, ShouldBeNil)
|
||||
@@ -209,9 +242,6 @@ func TestLoadConfig(t *testing.T) {
|
||||
Convey("Test viper load config", t, func(c C) {
|
||||
config := config.New()
|
||||
So(func() { cli.LoadConfiguration(config, "../../examples/config-policy.json") }, ShouldNotPanic)
|
||||
adminPolicy := viper.GetStringMapStringSlice("http.accessControl.adminPolicy")
|
||||
So(config.AccessControl.AdminPolicy.Actions, ShouldResemble, adminPolicy["actions"])
|
||||
So(config.AccessControl.AdminPolicy.Users, ShouldResemble, adminPolicy["users"])
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user