package config import ( "log/slog" "os" "reflect" "strconv" "time" ) type Config struct { // time configuration TimeFormat string `default:"2006-01-02 15:04:05" env:"time_format"` TimeZoneLocal string `default:"America/Chicago" env:"time_zone"` TZLocal *time.Location `ignored:"true"` TZUTC *time.Location `ignored:"true"` // logging LogLevel int `default:"50" env:"log_level"` Log *slog.Logger `ignored:"true"` SLogLevel *slog.LevelVar `ignored:"true"` // webserver WebServerPort int `default:"8080" env:"webserver_port"` WebServerIP string `default:"0.0.0.0" env:"webserver_ip"` WebServerReadTimeout int `default:"5" env:"webserver_read_timeout"` WebServerWriteTimeout int `default:"1" env:"webserver_write_timeout"` WebServerIdleTimeout int `default:"2" env:"webserver_idle_timeout"` // cisa RemoteURL string `default:"https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json?sort_by=field_date_added" env:"remote_url"` RefreshSeconds int `default:"14400" env:"refresh_seconds"` // nsupdate NSUKey string `env:"nsupdate-key" secret:"true"` NSUPort int `default:"53" env:"nsupdate-port"` NSUServer string `default:"ns1.example.com" env:"nsupdate-server"` NSUZone string `default:"example.com" env:"nsupdate-zone"` } // New initializes the config variable for use with a prepared set of defaults. func New() Config { cfg := Config{ SLogLevel: new(slog.LevelVar), } cfg.Log = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ Level: cfg.SLogLevel, })) return cfg } func setLogLevel(cfg *Config) { switch { // error case cfg.LogLevel <= 20: cfg.SLogLevel.Set(slog.LevelError) cfg.Log.Info("Log level updated", "level", slog.LevelError) // warning case cfg.LogLevel > 20 && cfg.LogLevel <= 40: cfg.SLogLevel.Set(slog.LevelWarn) cfg.Log.Info("Log level updated", "level", slog.LevelWarn) // info case cfg.LogLevel > 40 && cfg.LogLevel <= 60: cfg.SLogLevel.Set(slog.LevelInfo) cfg.Log.Info("Log level updated", "level", slog.LevelInfo) // debug case cfg.LogLevel > 60: cfg.SLogLevel.Set(slog.LevelDebug) cfg.Log.Info("Log level updated", "level", slog.LevelDebug) } // set default logger slog.SetDefault(cfg.Log) } func printRunningConfig(cfg *Config, cfgInfo []structInfo) { for _, info := range cfgInfo { if info.Secret { cfg.Log.Debug("Running Configuration", info.Alt, "REDACTED") } else { switch info.Type.String() { case "string": p := reflect.ValueOf(cfg).Elem().FieldByName(info.Name).Addr().Interface().(*string) cfg.Log.Debug("Running Configuration", info.Alt, *p) case "bool": p := reflect.ValueOf(cfg).Elem().FieldByName(info.Name).Addr().Interface().(*bool) cfg.Log.Debug("Running Configuration", info.Alt, strconv.FormatBool(*p)) case "int": p := reflect.ValueOf(cfg).Elem().FieldByName(info.Name).Addr().Interface().(*int) cfg.Log.Debug("Running Configuration", info.Alt, strconv.FormatInt(int64(*p), 10)) } } } }