mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-30 10:56:28 +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
|
lvl = options.LogLevel
|
||||||
}
|
}
|
||||||
if lvl == "" {
|
if lvl == "" {
|
||||||
lvl = "debug"
|
lvl = config.LogLevelDebug
|
||||||
}
|
}
|
||||||
|
|
||||||
switch lvl {
|
switch lvl {
|
||||||
case "trace", "debug", "info":
|
case config.LogLevelTrace, config.LogLevelDebug, config.LogLevelInfo:
|
||||||
default:
|
default:
|
||||||
// don't log access requests for levels > info
|
// don't log access requests for levels > info
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -41,6 +41,6 @@ func (mgr *LogManager) OnConfigChange(_ context.Context, cfg *Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Options.LogLevel != "" {
|
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.
|
// 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".
|
// 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.
|
// ProxyLogLevel sets the log level for the proxy service.
|
||||||
// Possible options are "info","warn", and "error". Defaults to the value of `LogLevel`.
|
// 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
|
// SharedKey is the shared secret authorization key used to mutually authenticate
|
||||||
// requests between services.
|
// requests between services.
|
||||||
|
@ -302,7 +302,7 @@ type certificateFilePair struct {
|
||||||
// DefaultOptions are the default configuration options for pomerium
|
// DefaultOptions are the default configuration options for pomerium
|
||||||
var defaultOptions = Options{
|
var defaultOptions = Options{
|
||||||
Debug: false,
|
Debug: false,
|
||||||
LogLevel: "info",
|
LogLevel: LogLevelInfo,
|
||||||
Services: "all",
|
Services: "all",
|
||||||
CookieHTTPOnly: true,
|
CookieHTTPOnly: true,
|
||||||
CookieSecure: true,
|
CookieSecure: true,
|
||||||
|
@ -741,6 +741,14 @@ func (o *Options) Validate() error {
|
||||||
return fmt.Errorf("config: invalid cookie_same_site: %w", err)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1320,8 +1328,8 @@ func (o *Options) ApplySettings(ctx context.Context, certsIndex *cryptutil.Certi
|
||||||
|
|
||||||
set(&o.InstallationID, settings.InstallationId)
|
set(&o.InstallationID, settings.InstallationId)
|
||||||
set(&o.Debug, settings.Debug)
|
set(&o.Debug, settings.Debug)
|
||||||
set(&o.LogLevel, settings.LogLevel)
|
setLogLevel(&o.LogLevel, settings.LogLevel)
|
||||||
set(&o.ProxyLogLevel, settings.ProxyLogLevel)
|
setLogLevel(&o.ProxyLogLevel, settings.ProxyLogLevel)
|
||||||
set(&o.SharedKey, settings.SharedSecret)
|
set(&o.SharedKey, settings.SharedSecret)
|
||||||
set(&o.Services, settings.Services)
|
set(&o.Services, settings.Services)
|
||||||
set(&o.Addr, settings.Address)
|
set(&o.Addr, settings.Address)
|
||||||
|
@ -1474,6 +1482,13 @@ func setDuration(dst *time.Duration, src *durationpb.Duration) {
|
||||||
*dst = src.AsDuration()
|
*dst = src.AsDuration()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setLogLevel(dst *LogLevel, src *string) {
|
||||||
|
if src == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
*dst = LogLevel(*src)
|
||||||
|
}
|
||||||
|
|
||||||
func setOptional[T any](dst **T, src *T) {
|
func setOptional[T any](dst **T, src *T) {
|
||||||
if src == nil {
|
if src == nil {
|
||||||
return
|
return
|
||||||
|
|
|
@ -64,22 +64,22 @@ func ZapLogger() *zap.Logger {
|
||||||
return zapLogger.Load()
|
return zapLogger.Load()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLevel sets the minimum global log level. Options are 'debug' 'info' 'warn' and 'error'.
|
// SetLevel sets the minimum global log level.
|
||||||
// Defaults to 'debug'
|
func SetLevel(level zerolog.Level) {
|
||||||
func SetLevel(level string) {
|
zerolog.SetGlobalLevel(level)
|
||||||
switch level {
|
switch level {
|
||||||
case "info":
|
case zerolog.DebugLevel, zerolog.TraceLevel:
|
||||||
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)
|
|
||||||
zapLevel.SetLevel(zapcore.DebugLevel)
|
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() {
|
func ExampleSetLevel() {
|
||||||
setup()
|
setup()
|
||||||
log.SetLevel("info")
|
log.SetLevel(zerolog.InfoLevel)
|
||||||
log.Debug(context.Background()).Msg("Debug")
|
log.Debug(context.Background()).Msg("Debug")
|
||||||
log.Info(context.Background()).Msg("Debug or Info")
|
log.Info(context.Background()).Msg("Debug or Info")
|
||||||
log.SetLevel("warn")
|
log.SetLevel(zerolog.WarnLevel)
|
||||||
log.Debug(context.Background()).Msg("Debug")
|
log.Debug(context.Background()).Msg("Debug")
|
||||||
log.Info(context.Background()).Msg("Debug or Info")
|
log.Info(context.Background()).Msg("Debug or Info")
|
||||||
log.Warn(context.Background()).Msg("Debug or Info or Warn")
|
log.Warn(context.Background()).Msg("Debug or Info or Warn")
|
||||||
log.SetLevel("error")
|
log.SetLevel(zerolog.ErrorLevel)
|
||||||
log.Debug(context.Background()).Msg("Debug")
|
log.Debug(context.Background()).Msg("Debug")
|
||||||
log.Info(context.Background()).Msg("Debug or Info")
|
log.Info(context.Background()).Msg("Debug or Info")
|
||||||
log.Warn(context.Background()).Msg("Debug or Info or Warn")
|
log.Warn(context.Background()).Msg("Debug or Info or Warn")
|
||||||
log.Error(context.Background()).Msg("Debug or Info or Warn or Error")
|
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")
|
log.Debug(context.Background()).Msg("Debug")
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
|
|
|
@ -37,7 +37,7 @@ const (
|
||||||
|
|
||||||
type serverOptions struct {
|
type serverOptions struct {
|
||||||
services string
|
services string
|
||||||
logLevel string
|
logLevel config.LogLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Server is a pomerium proxy implemented via envoy.
|
// 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{
|
options := serverOptions{
|
||||||
services: cfg.Options.Services,
|
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{})) {
|
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{
|
args := []string{
|
||||||
"-c", configFileName,
|
"-c", configFileName,
|
||||||
"--log-level", srv.options.logLevel,
|
"--log-level", srv.options.logLevel.ToEnvoy(),
|
||||||
"--log-format", "[LOG_FORMAT]%l--%n--%v",
|
"--log-format", "[LOG_FORMAT]%l--%n--%v",
|
||||||
"--log-format-escaped",
|
"--log-format-escaped",
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
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 {
|
for _, a := range args {
|
||||||
if a != "" {
|
if a != "" {
|
||||||
return a
|
return a
|
||||||
|
|
Loading…
Add table
Reference in a new issue