Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions pkg/cli/server/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,13 @@ func LoadConfiguration(config *config.Config, configPath string) error {
return err
}

// Validate log level before creating logger to avoid panic
if _, err := zlog.ParseLevel(config.Log.Level); err != nil {
logger.Error().Err(zerr.ErrBadConfig).Str("level", config.Log.Level).Msg(err.Error())
Comment thread
andaaron marked this conversation as resolved.

return err
}

log := zlog.NewLogger(config.Log.Level, config.Log.Output)

if len(metaData.Keys) == 0 {
Expand Down
24 changes: 24 additions & 0 deletions pkg/cli/server/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,30 @@ storage:
So(err, ShouldBeNil)
})

Convey("Test verify config with invalid log level", t, func(c C) {
content := `{"distSpecVersion":"1.1.1","storage":{"rootDirectory":"/tmp/zot"},
"http":{"address":"127.0.0.1","port":"8080","realm":"zot"},
"log":{"level":"invalid"}}`
tmpfile := MakeTempFileWithContent(t, "zot-test.json", content)

os.Args = []string{"cli_test", "verify", tmpfile}
err := cli.NewServerRootCmd().Execute()
So(err, ShouldNotBeNil)
So(err.Error(), ShouldContainSubstring, "invalid log level")
So(err.Error(), ShouldContainSubstring, "invalid")
})

Convey("Test verify config with valid trace log level", t, func(c C) {
content := `{"distSpecVersion":"1.1.1","storage":{"rootDirectory":"/tmp/zot"},
"http":{"address":"127.0.0.1","port":"8080","realm":"zot"},
"log":{"level":"trace"}}`
tmpfile := MakeTempFileWithContent(t, "zot-test.json", content)

os.Args = []string{"cli_test", "verify", tmpfile}
err := cli.NewServerRootCmd().Execute()
So(err, ShouldBeNil)
})

Convey("Test verify CVE warn for remote storage", t, func(c C) {
content := `{
"storage":{
Expand Down
17 changes: 10 additions & 7 deletions pkg/log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,19 +258,22 @@ func (e *Event) Msg(msg string) {
}
}

// parseLevel converts string level to slog.Level.
func parseLevel(level string) (slog.Level, error) {
// ParseLevel converts string level to slog.Level.
func ParseLevel(level string) (slog.Level, error) {
const supportedLevels = "debug, trace, info, warn, warning, error, fatal, panic"

switch strings.ToLower(level) {
case "debug":
case "debug", "trace":
return slog.LevelDebug, nil
case "info":
return slog.LevelInfo, nil
case "warn", "warning":
return slog.LevelWarn, nil
case "error":
case "error", "fatal", "panic":
return slog.LevelError, nil
Comment thread
andaaron marked this conversation as resolved.
default:
return slog.LevelInfo, errors.ErrBadConfig
return slog.LevelInfo, fmt.Errorf("%w: invalid log level '%s', supported levels are: %s",
errors.ErrBadConfig, level, supportedLevels)
}
}

Expand All @@ -292,7 +295,7 @@ func NewLogger(level, output string) Logger {

func NewAuditLogger(level, output string) *Logger {
// Parse log level
lvl, err := parseLevel(level)
lvl, err := ParseLevel(level)
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -343,7 +346,7 @@ func defaultJSONHandler(lvl slog.Leveler, writer io.Writer) *slog.JSONHandler {

func NewLoggerWithWriter(level string, writer io.Writer) Logger {
// Parse log level
lvl, err := parseLevel(level)
lvl, err := ParseLevel(level)
if err != nil {
panic(err)
}
Expand Down
Loading