mirror of
https://github.com/project-zot/zot.git
synced 2026-06-17 12:58:02 +08:00
feat(jwt-asm): support AWS Secrets Manager for JWT verification (#3763)
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
This commit is contained in:
@@ -580,6 +580,10 @@ func validateConfiguration(config *config.Config, logger zlog.Logger) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := validateBearerConfig(config, logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := validateSync(config, logger); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -711,6 +715,49 @@ func validateOpenIDConfig(cfg *config.Config, logger zlog.Logger) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateBearerConfig(cfg *config.Config, logger zlog.Logger) error {
|
||||
authConfig := cfg.CopyAuthConfig()
|
||||
if authConfig == nil || authConfig.Bearer == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
bearer := authConfig.Bearer
|
||||
|
||||
if bearer.Cert != "" && bearer.AWSSecretsManager != nil {
|
||||
msg := "cannot configure both cert and awsSecretsManager for bearer authentication"
|
||||
logger.Error().Err(zerr.ErrBadConfig).Msg(msg)
|
||||
|
||||
return fmt.Errorf("%w: %s", zerr.ErrBadConfig, msg)
|
||||
}
|
||||
|
||||
if bearer.AWSSecretsManager != nil {
|
||||
asm := bearer.AWSSecretsManager
|
||||
|
||||
if asm.Region == "" {
|
||||
msg := "awsSecretsManager region must be specified"
|
||||
logger.Error().Err(zerr.ErrBadConfig).Msg(msg)
|
||||
|
||||
return fmt.Errorf("%w: %s", zerr.ErrBadConfig, msg)
|
||||
}
|
||||
|
||||
if asm.SecretName == "" {
|
||||
msg := "awsSecretsManager secretName must be specified"
|
||||
logger.Error().Err(zerr.ErrBadConfig).Msg(msg)
|
||||
|
||||
return fmt.Errorf("%w: %s", zerr.ErrBadConfig, msg)
|
||||
}
|
||||
|
||||
if asm.RefreshInterval < 0 {
|
||||
msg := "awsSecretsManager refreshInterval must be non-negative"
|
||||
logger.Error().Err(zerr.ErrBadConfig).Msg(msg)
|
||||
|
||||
return fmt.Errorf("%w: %s", zerr.ErrBadConfig, msg)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateAuthzPolicies(config *config.Config, logger zlog.Logger) error {
|
||||
authConfig := config.CopyAuthConfig()
|
||||
accessControlConfig := config.CopyAccessControlConfig()
|
||||
|
||||
@@ -3079,3 +3079,107 @@ func TestRetentionDelayDefaults(t *testing.T) {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBearerASMConfigValidation(t *testing.T) {
|
||||
Convey("Test bearer ASM config validation", t, func() {
|
||||
Convey("Reject both cert and awsSecretsManager", func() {
|
||||
content := `{
|
||||
"storage": {"rootDirectory": "/tmp/zot"},
|
||||
"http": {
|
||||
"address": "127.0.0.1", "port": "8080",
|
||||
"auth": {
|
||||
"bearer": {
|
||||
"realm": "test", "service": "test",
|
||||
"cert": "/some/cert.pem",
|
||||
"awsSecretsManager": {"region": "us-east-1", "secretName": "my-secret"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
cfg := config.New()
|
||||
tmpfile := MakeTempFileWithContent(t, "zot-test.json", content)
|
||||
err := cli.LoadConfiguration(cfg, tmpfile)
|
||||
So(err, ShouldNotBeNil)
|
||||
So(err, ShouldWrap, zerr.ErrBadConfig)
|
||||
})
|
||||
|
||||
Convey("Reject empty region", func() {
|
||||
content := `{
|
||||
"storage": {"rootDirectory": "/tmp/zot"},
|
||||
"http": {
|
||||
"address": "127.0.0.1", "port": "8080",
|
||||
"auth": {
|
||||
"bearer": {
|
||||
"realm": "test", "service": "test",
|
||||
"awsSecretsManager": {"region": "", "secretName": "my-secret"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
cfg := config.New()
|
||||
tmpfile := MakeTempFileWithContent(t, "zot-test.json", content)
|
||||
err := cli.LoadConfiguration(cfg, tmpfile)
|
||||
So(err, ShouldNotBeNil)
|
||||
So(err, ShouldWrap, zerr.ErrBadConfig)
|
||||
})
|
||||
|
||||
Convey("Reject empty secretName", func() {
|
||||
content := `{
|
||||
"storage": {"rootDirectory": "/tmp/zot"},
|
||||
"http": {
|
||||
"address": "127.0.0.1", "port": "8080",
|
||||
"auth": {
|
||||
"bearer": {
|
||||
"realm": "test", "service": "test",
|
||||
"awsSecretsManager": {"region": "us-east-1", "secretName": ""}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
cfg := config.New()
|
||||
tmpfile := MakeTempFileWithContent(t, "zot-test.json", content)
|
||||
err := cli.LoadConfiguration(cfg, tmpfile)
|
||||
So(err, ShouldNotBeNil)
|
||||
So(err, ShouldWrap, zerr.ErrBadConfig)
|
||||
})
|
||||
|
||||
Convey("Reject negative refreshInterval", func() {
|
||||
content := `{
|
||||
"storage": {"rootDirectory": "/tmp/zot"},
|
||||
"http": {
|
||||
"address": "127.0.0.1", "port": "8080",
|
||||
"auth": {
|
||||
"bearer": {
|
||||
"realm": "test", "service": "test",
|
||||
"awsSecretsManager": {"region": "us-east-1", "secretName": "my-secret", "refreshInterval": "-1s"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
cfg := config.New()
|
||||
tmpfile := MakeTempFileWithContent(t, "zot-test.json", content)
|
||||
err := cli.LoadConfiguration(cfg, tmpfile)
|
||||
So(err, ShouldNotBeNil)
|
||||
So(err, ShouldWrap, zerr.ErrBadConfig)
|
||||
})
|
||||
|
||||
Convey("Valid ASM config is accepted", func() {
|
||||
content := `{
|
||||
"storage": {"rootDirectory": "/tmp/zot"},
|
||||
"http": {
|
||||
"address": "127.0.0.1", "port": "8080",
|
||||
"auth": {
|
||||
"bearer": {
|
||||
"realm": "test", "service": "test",
|
||||
"awsSecretsManager": {"region": "us-east-1", "secretName": "my-secret"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
cfg := config.New()
|
||||
tmpfile := MakeTempFileWithContent(t, "zot-test.json", content)
|
||||
err := cli.LoadConfiguration(cfg, tmpfile)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user