mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-29 18:36:30 +02:00
config: validate log levels (#4367)
* config: validate log levels * fix SetLevel * document unset, merge warn/warning
This commit is contained in:
parent
a1388592d8
commit
78e7a3e7d0
8 changed files with 152 additions and 30 deletions
|
@ -82,11 +82,11 @@ func buildAccessLogs(options *config.Options) []*envoy_config_accesslog_v3.Acces
|
|||
lvl = options.LogLevel
|
||||
}
|
||||
if lvl == "" {
|
||||
lvl = "debug"
|
||||
lvl = config.LogLevelDebug
|
||||
}
|
||||
|
||||
switch lvl {
|
||||
case "trace", "debug", "info":
|
||||
case config.LogLevelTrace, config.LogLevelDebug, config.LogLevelInfo:
|
||||
default:
|
||||
// don't log access requests for levels > info
|
||||
return nil
|
||||
|
|
|
@ -41,6 +41,6 @@ func (mgr *LogManager) OnConfigChange(_ context.Context, cfg *Config) {
|
|||
}
|
||||
|
||||
if cfg.Options.LogLevel != "" {
|
||||
log.SetLevel(cfg.Options.LogLevel)
|
||||
log.SetLevel(cfg.Options.LogLevel.ToZerolog())
|
||||
}
|
||||
}
|
||||
|
|
107
config/log_level.go
Normal file
107
config/log_level.go
Normal file
|
@ -0,0 +1,107 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// A LogLevel represents a logging level.
|
||||
type LogLevel string
|
||||
|
||||
// Known log levels.
|
||||
const (
|
||||
LogLevelUnset LogLevel = "" // defaults to info
|
||||
LogLevelTrace LogLevel = "trace"
|
||||
LogLevelDebug LogLevel = "debug"
|
||||
LogLevelInfo LogLevel = "info"
|
||||
LogLevelWarn LogLevel = "warn"
|
||||
LogLevelWarning LogLevel = "warning"
|
||||
LogLevelError LogLevel = "error"
|
||||
LogLevelCritical LogLevel = "critical"
|
||||
LogLevelFatal LogLevel = "fatal"
|
||||
LogLevelPanic LogLevel = "panic"
|
||||
LogLevelOff LogLevel = "off"
|
||||
LogLevelNone LogLevel = "none"
|
||||
LogLevelDisabled LogLevel = "disabled"
|
||||
)
|
||||
|
||||
// AllLogLevels are all of the known log levels.
|
||||
var AllLogLevels = [...]LogLevel{
|
||||
LogLevelUnset,
|
||||
LogLevelTrace,
|
||||
LogLevelDebug,
|
||||
LogLevelInfo,
|
||||
LogLevelWarn,
|
||||
LogLevelWarning,
|
||||
LogLevelError,
|
||||
LogLevelCritical,
|
||||
LogLevelFatal,
|
||||
LogLevelPanic,
|
||||
LogLevelOff,
|
||||
LogLevelNone,
|
||||
LogLevelDisabled,
|
||||
}
|
||||
|
||||
var logLevelLookup = func() map[LogLevel]struct{} {
|
||||
m := map[LogLevel]struct{}{}
|
||||
for _, lvl := range AllLogLevels {
|
||||
m[lvl] = struct{}{}
|
||||
}
|
||||
return m
|
||||
}()
|
||||
|
||||
// ValidateLogLevel validates that a log level is one of the known log levels.
|
||||
func ValidateLogLevel(lvl LogLevel) error {
|
||||
_, ok := logLevelLookup[lvl]
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown log level: %s", lvl)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToZerolog converts the log level to a level zerolog expects
|
||||
func (lvl LogLevel) ToZerolog() zerolog.Level {
|
||||
switch lvl {
|
||||
case LogLevelTrace:
|
||||
return zerolog.TraceLevel
|
||||
case LogLevelDebug:
|
||||
return zerolog.DebugLevel
|
||||
case LogLevelInfo, LogLevelUnset:
|
||||
return zerolog.InfoLevel
|
||||
case LogLevelWarn, LogLevelWarning:
|
||||
return zerolog.WarnLevel
|
||||
case LogLevelError:
|
||||
return zerolog.ErrorLevel
|
||||
case LogLevelCritical, LogLevelFatal:
|
||||
return zerolog.FatalLevel
|
||||
case LogLevelPanic:
|
||||
return zerolog.PanicLevel
|
||||
case LogLevelOff, LogLevelNone, LogLevelDisabled:
|
||||
return zerolog.Disabled
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown log level: %s", lvl))
|
||||
}
|
||||
}
|
||||
|
||||
// ToEnvoy converts the log level to a string envoy expects.
|
||||
func (lvl LogLevel) ToEnvoy() string {
|
||||
switch lvl {
|
||||
case LogLevelTrace:
|
||||
return "trace"
|
||||
case LogLevelDebug:
|
||||
return "debug"
|
||||
case LogLevelInfo, LogLevelUnset:
|
||||
return "info"
|
||||
case LogLevelWarn, LogLevelWarning:
|
||||
return "warn"
|
||||
case LogLevelError:
|
||||
return "error"
|
||||
case LogLevelCritical, LogLevelFatal, LogLevelPanic:
|
||||
return "critical"
|
||||
case LogLevelOff, LogLevelNone, LogLevelDisabled:
|
||||
return "off"
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown log level: %s", lvl))
|
||||
}
|
||||
}
|
|
@ -62,11 +62,11 @@ type Options struct {
|
|||
|
||||
// LogLevel sets the global override for log level. All Loggers will use at least this value.
|
||||
// Possible options are "info","warn","debug" and "error". Defaults to "info".
|
||||
LogLevel string `mapstructure:"log_level" yaml:"log_level,omitempty"`
|
||||
LogLevel LogLevel `mapstructure:"log_level" yaml:"log_level,omitempty"`
|
||||
|
||||
// ProxyLogLevel sets the log level for the proxy service.
|
||||
// Possible options are "info","warn", and "error". Defaults to the value of `LogLevel`.
|
||||
ProxyLogLevel string `mapstructure:"proxy_log_level" yaml:"proxy_log_level,omitempty"`
|
||||
ProxyLogLevel LogLevel `mapstructure:"proxy_log_level" yaml:"proxy_log_level,omitempty"`
|
||||
|
||||
// SharedKey is the shared secret authorization key used to mutually authenticate
|
||||
// requests between services.
|
||||
|
@ -302,7 +302,7 @@ type certificateFilePair struct {
|
|||
// DefaultOptions are the default configuration options for pomerium
|
||||
var defaultOptions = Options{
|
||||
Debug: false,
|
||||
LogLevel: "info",
|
||||
LogLevel: LogLevelInfo,
|
||||
Services: "all",
|
||||
CookieHTTPOnly: true,
|
||||
CookieSecure: true,
|
||||
|
@ -741,6 +741,14 @@ func (o *Options) Validate() error {
|
|||
return fmt.Errorf("config: invalid cookie_same_site: %w", err)
|
||||
}
|
||||
|
||||
if err := ValidateLogLevel(o.LogLevel); err != nil {
|
||||
return fmt.Errorf("config: invalid log_level: %w", err)
|
||||
}
|
||||
|
||||
if err := ValidateLogLevel(o.ProxyLogLevel); err != nil {
|
||||
return fmt.Errorf("config: invalid proxy_log_level: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1320,8 +1328,8 @@ func (o *Options) ApplySettings(ctx context.Context, certsIndex *cryptutil.Certi
|
|||
|
||||
set(&o.InstallationID, settings.InstallationId)
|
||||
set(&o.Debug, settings.Debug)
|
||||
set(&o.LogLevel, settings.LogLevel)
|
||||
set(&o.ProxyLogLevel, settings.ProxyLogLevel)
|
||||
setLogLevel(&o.LogLevel, settings.LogLevel)
|
||||
setLogLevel(&o.ProxyLogLevel, settings.ProxyLogLevel)
|
||||
set(&o.SharedKey, settings.SharedSecret)
|
||||
set(&o.Services, settings.Services)
|
||||
set(&o.Addr, settings.Address)
|
||||
|
@ -1474,6 +1482,13 @@ func setDuration(dst *time.Duration, src *durationpb.Duration) {
|
|||
*dst = src.AsDuration()
|
||||
}
|
||||
|
||||
func setLogLevel(dst *LogLevel, src *string) {
|
||||
if src == nil {
|
||||
return
|
||||
}
|
||||
*dst = LogLevel(*src)
|
||||
}
|
||||
|
||||
func setOptional[T any](dst **T, src *T) {
|
||||
if src == nil {
|
||||
return
|
||||
|
|
|
@ -64,22 +64,22 @@ func ZapLogger() *zap.Logger {
|
|||
return zapLogger.Load()
|
||||
}
|
||||
|
||||
// SetLevel sets the minimum global log level. Options are 'debug' 'info' 'warn' and 'error'.
|
||||
// Defaults to 'debug'
|
||||
func SetLevel(level string) {
|
||||
// SetLevel sets the minimum global log level.
|
||||
func SetLevel(level zerolog.Level) {
|
||||
zerolog.SetGlobalLevel(level)
|
||||
switch level {
|
||||
case "info":
|
||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||
zapLevel.SetLevel(zapcore.InfoLevel)
|
||||
case "warn":
|
||||
zerolog.SetGlobalLevel(zerolog.WarnLevel)
|
||||
zapLevel.SetLevel(zapcore.WarnLevel)
|
||||
case "error":
|
||||
zerolog.SetGlobalLevel(zerolog.ErrorLevel)
|
||||
zapLevel.SetLevel(zapcore.ErrorLevel)
|
||||
default:
|
||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||
case zerolog.DebugLevel, zerolog.TraceLevel:
|
||||
zapLevel.SetLevel(zapcore.DebugLevel)
|
||||
case zerolog.WarnLevel:
|
||||
zapLevel.SetLevel(zapcore.WarnLevel)
|
||||
case zerolog.ErrorLevel:
|
||||
zapLevel.SetLevel(zapcore.ErrorLevel)
|
||||
case zerolog.FatalLevel:
|
||||
zapLevel.SetLevel(zapcore.FatalLevel)
|
||||
case zerolog.PanicLevel:
|
||||
zapLevel.SetLevel(zapcore.PanicLevel)
|
||||
default:
|
||||
zapLevel.SetLevel(zapcore.InfoLevel)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -134,19 +134,19 @@ func Example() {
|
|||
|
||||
func ExampleSetLevel() {
|
||||
setup()
|
||||
log.SetLevel("info")
|
||||
log.SetLevel(zerolog.InfoLevel)
|
||||
log.Debug(context.Background()).Msg("Debug")
|
||||
log.Info(context.Background()).Msg("Debug or Info")
|
||||
log.SetLevel("warn")
|
||||
log.SetLevel(zerolog.WarnLevel)
|
||||
log.Debug(context.Background()).Msg("Debug")
|
||||
log.Info(context.Background()).Msg("Debug or Info")
|
||||
log.Warn(context.Background()).Msg("Debug or Info or Warn")
|
||||
log.SetLevel("error")
|
||||
log.SetLevel(zerolog.ErrorLevel)
|
||||
log.Debug(context.Background()).Msg("Debug")
|
||||
log.Info(context.Background()).Msg("Debug or Info")
|
||||
log.Warn(context.Background()).Msg("Debug or Info or Warn")
|
||||
log.Error(context.Background()).Msg("Debug or Info or Warn or Error")
|
||||
log.SetLevel("default-fall-through")
|
||||
log.SetLevel(zerolog.DebugLevel)
|
||||
log.Debug(context.Background()).Msg("Debug")
|
||||
|
||||
// Output:
|
||||
|
|
|
@ -37,7 +37,7 @@ const (
|
|||
|
||||
type serverOptions struct {
|
||||
services string
|
||||
logLevel string
|
||||
logLevel config.LogLevel
|
||||
}
|
||||
|
||||
// A Server is a pomerium proxy implemented via envoy.
|
||||
|
@ -113,7 +113,7 @@ func (srv *Server) update(ctx context.Context, cfg *config.Config) {
|
|||
|
||||
options := serverOptions{
|
||||
services: cfg.Options.Services,
|
||||
logLevel: firstNonEmpty(cfg.Options.ProxyLogLevel, cfg.Options.LogLevel, "debug"),
|
||||
logLevel: firstNonEmpty(cfg.Options.ProxyLogLevel, cfg.Options.LogLevel, config.LogLevelDebug),
|
||||
}
|
||||
|
||||
if cmp.Equal(srv.options, options, cmp.AllowUnexported(serverOptions{})) {
|
||||
|
@ -140,7 +140,7 @@ func (srv *Server) run(ctx context.Context, cfg *config.Config) error {
|
|||
|
||||
args := []string{
|
||||
"-c", configFileName,
|
||||
"--log-level", srv.options.logLevel,
|
||||
"--log-level", srv.options.logLevel.ToEnvoy(),
|
||||
"--log-format", "[LOG_FORMAT]%l--%n--%v",
|
||||
"--log-format-escaped",
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
||||
)
|
||||
|
||||
func firstNonEmpty(args ...string) string {
|
||||
func firstNonEmpty[T interface{ ~string }](args ...T) T {
|
||||
for _, a := range args {
|
||||
if a != "" {
|
||||
return a
|
||||
|
|
Loading…
Add table
Reference in a new issue