Skip to content

Commit

Permalink
Fix (config): Logger config persistence, implement syslog (tested wor…
Browse files Browse the repository at this point in the history
…king)
  • Loading branch information
yunginnanet committed Jun 26, 2024
1 parent e43c603 commit e31113b
Show file tree
Hide file tree
Showing 12 changed files with 268 additions and 101 deletions.
12 changes: 7 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
all: deps check build
format:
format :
find . -iname "*.go" -exec gofmt -s -l -w {} \;
check:
check :
go vet ./...
run:
run :
go run cmd/HellPot/*.go
deps:
go mod tidy -v
build:
go build -trimpath -ldflags "-s -w -X main.version=`git tag --sort=-version:refname | head -n 1`" cmd/HellPot/*.go
test :
go test -v ./...
build :
go build -x -trimpath -ldflags "-s -w -X main.version=`git tag --sort=-version:refname | head -n 1`" cmd/HellPot/*.go
2 changes: 2 additions & 0 deletions cmd/HellPot/HellPot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
)

func testMain(t *testing.T) (string, string, chan os.Signal, *config.Parameters, error) {
t.Setenv("HELLPOT_TEST_MODE", "true")
t.Helper()
stopChan := make(chan os.Signal, 1)

Expand All @@ -39,6 +40,7 @@ func TestHellPot(t *testing.T) {
}
confFile := filepath.Join(tDir, "HellPot_test.toml")
t.Setenv("HELLPOT_LOGGER_DIRECTORY", logDir)
t.Setenv("HELLPOT_LOGGER_RSYSLOG_ADDRESS", "local")
t.Setenv("HELLPOT_CONFIG", confFile)

resolvedConf, logFile, stopChan, realConfig, err := testMain(t)
Expand Down
123 changes: 61 additions & 62 deletions cmd/HellPot/boot.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"errors"
"flag"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -86,15 +85,17 @@ func readConfig(resolvedConf string) (*config.Parameters, error) {
var runningConfig *config.Parameters

f, err = os.Open(resolvedConf) // #nosec G304 go home gosec, you're drunk
defer func() {
if f != nil {
_ = f.Close()
}
}()
if err == nil {
runningConfig, setupErr = config.Setup(f)
}
switch {
case setupErr != nil:
println("failed to setup config: " + setupErr.Error())
if f != nil {
_ = f.Close()
}
err = setupErr
case err != nil:
println("failed to open config file for reading: " + err.Error())
Expand All @@ -105,26 +106,22 @@ func readConfig(resolvedConf string) (*config.Parameters, error) {
}
println("failed to create config file, cannot continue")
return nil, fmt.Errorf("failed to create config file: %w", err)
case runningConfig != nil:
_ = f.Close()
case runningConfig == nil:
err = errors.New("unknown failure resulting in missing configuration, cannot continue")
return nil, err
}

return runningConfig, err
}

func resolveConfig() (runningConfig *config.Parameters, usingDefaults bool, resolvedConf string, err error) {
setIfPresent := func(confRoot *flag.Flag) (ok bool) {
if confRoot != nil && confRoot.Value.String() != "" {
resolvedConf = confRoot.Value.String()
return true
}
return false
}
if config.CLIFlags != nil {
confRoot := config.CLIFlags.Lookup("config")
if !setIfPresent(confRoot) {
confRoot = config.CLIFlags.Lookup("c")
setIfPresent(confRoot)
conf := config.CLIFlags.Lookup("config")
if conf != nil && conf.Value.String() != "" {
resolvedConf = conf.Value.String()
if runningConfig, err = readConfig(resolvedConf); err != nil {
return runningConfig, false, resolvedConf, err
}
}
}

Expand Down Expand Up @@ -153,62 +150,64 @@ func resolveConfig() (runningConfig *config.Parameters, usingDefaults bool, reso
return runningConfig, false, resolvedConf, nil
}

func setup(stopChan chan os.Signal) (log zerolog.Logger, logFile string,
resolvedConf string, realConf *config.Parameters, err error) {

config.InitCLI()

var usingDefaults bool
var runningConfig *config.Parameters

if runningConfig, usingDefaults, resolvedConf, err = resolveConfig(); err != nil {
func initLogger(runningConfig *config.Parameters) (log zerolog.Logger, logFile string, err error) {
if log, err = logger.New(&runningConfig.Logger); err != nil {
return
}

if runningConfig == nil {
err = errors.New("running configuration is nil, cannot continue")
return
}
logFile = runningConfig.Logger.ActiveLogFileName

// TODO: jesus bro r u ok
realConf = runningConfig
if usingDefaults && !realConf.UsingDefaults {
realConf.UsingDefaults = true
}
if realConf.UsingDefaults && !usingDefaults {
usingDefaults = true
}
return
}

//goland:noinspection GoNilness // we check for nil above
if log, err = logger.New(runningConfig.Logger); err != nil {
return
}
func setup(stopChan chan os.Signal) (log zerolog.Logger, logFile string,
resolvedConf string, runningConfig *config.Parameters, err error) {

logFile = runningConfig.Logger.ActiveLogFileName
config.InitCLI()

var usingDefaults bool

if usingDefaults {
log.Warn().Msg("using default configuration!")
print(red + "continuing with default configuration in ")
for i := defaultConfigWarningDelaySecs; i > 0; i-- {
print(strconv.Itoa(i))
for i := 0; i < 5; i++ {
time.Sleep(200 * time.Millisecond)
print(".")
defer func() {
if runningConfig == nil && err == nil {
err = errors.New("running configuration is nil, cannot continue")
return
}
if usingDefaults && os.Getenv("HELLPOT_TEST_MODE") == "" {
log.Warn().Msg("using default configuration!")
print(red + "continuing with default configuration in ")
for i := defaultConfigWarningDelaySecs; i > 0; i-- {
print(strconv.Itoa(i))
for i := 0; i < 5; i++ {
time.Sleep(200 * time.Millisecond)
print(".")
}
}
print(reset + "\n")
}
print(reset + "\n")
}
signal.Notify(stopChan, syscall.SIGINT, syscall.SIGTERM)

if //goland:noinspection GoNilness
!runningConfig.Logger.NoColor {
extra.Banner()
}

signal.Notify(stopChan, syscall.SIGINT, syscall.SIGTERM)
if //goland:noinspection GoNilness
!runningConfig.Logger.NoColor {
extra.Banner()
}
if absResolvedConf, err := filepath.Abs(resolvedConf); err == nil {
resolvedConf = absResolvedConf
}
}()

if absResolvedConf, err := filepath.Abs(resolvedConf); err == nil {
resolvedConf = absResolvedConf
switch {
case config.CLIFlags.Lookup("config") == nil, config.CLIFlags.Lookup("genconfig").Value.String() == "":
if runningConfig, usingDefaults, resolvedConf, err = resolveConfig(); err != nil {
return
}
log, logFile, err = initLogger(runningConfig)
default:
println("loading configuration file: " + config.CLIFlags.Lookup("config").Value.String())
if runningConfig, err = readConfig(config.CLIFlags.Lookup("config").Value.String()); err != nil {
return
}
resolvedConf = config.CLIFlags.Lookup("config").Value.String()
log, logFile, err = initLogger(runningConfig)
}

return
}
8 changes: 4 additions & 4 deletions internal/config/client_rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import (

type ClientRules struct {
// See: https://github.com/yunginnanet/HellPot/issues/23
UseragentDisallowStrings []string `koanf:"user_agent_disallow_strings"`
useragentDisallowStrBytes [][]byte `koanf:"-"`
UseragentDisallowRegex []string `koanf:"user_agent_disallow_regex"`
useragentDisallowRegex []*regexp.Regexp `koanf:"-"`
UseragentDisallowStrings []string `koanf:"user_agent_disallow_strings"`
useragentDisallowStrBytes [][]byte
UseragentDisallowRegex []string `koanf:"user_agent_disallow_regex"`
useragentDisallowRegex []*regexp.Regexp
}

func NewClientRules(strs []string, regex []string) (*ClientRules, error) {
Expand Down
File renamed without changes.
25 changes: 25 additions & 0 deletions internal/config/command_line.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"
"os"
"slices"
"strconv"
"strings"

"github.com/yunginnanet/HellPot/internal/extra"
Expand Down Expand Up @@ -87,6 +88,30 @@ func InitCLI() {
println(err.Error())
os.Exit(2)
}

for defaultKey, defaultVal := range Defaults.val {
switch defaultVal.(type) {
case bool:
parsedBool, pErr := strconv.ParseBool(CLIFlags.Lookup(defaultKey).Value.String())
if pErr != nil {
continue
}
if parsedBool == Defaults.val[defaultKey].(bool) {
fl := CLIFlags.Lookup(defaultKey)
*fl = flag.Flag{}
fl = nil
}
case string:
if CLIFlags.Lookup(defaultKey).Value.String() == Defaults.val[defaultKey].(string) ||
CLIFlags.Lookup(defaultKey).Value.String() == "" {
fl := CLIFlags.Lookup(defaultKey)
*fl = flag.Flag{}
fl = nil
}
}

}

if os.Getenv("HELLPOT_CONFIG") != "" {
if err := CLIFlags.Set("config", os.Getenv("HELLPOT_CONFIG")); err != nil {
panic(err)
Expand Down
1 change: 1 addition & 0 deletions internal/config/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ var defOpts = map[string]interface{}{
"noconsole": false,
"use_date_filename": false,
"docker_logging": false,
"rsyslog_address": "",
"console_time_format": time.Kitchen,
},
"http": map[string]interface{}{
Expand Down
1 change: 1 addition & 0 deletions internal/config/defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func TestDefaults(t *testing.T) {
"http",
"performance",
"deception",
"bespoke",
} {
total += bytes.Count(bs, []byte(needle)) + 3 // name plus brackets and newline
if !bytes.Contains(bs, []byte(needle)) {
Expand Down
10 changes: 5 additions & 5 deletions internal/config/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import (

// Parameters represents the configuration for HellPot.
type Parameters struct {
HTTP HTTP `koanf:"http"`
Logger *logger.Configuration `koanf:"logger"`
Bespoke Customization `koanf:"bespoke"`
Perf Performance `koanf:"performance"`
Liar Deception `koanf:"deception"`
HTTP HTTP `koanf:"http"`
Logger logger.Configuration `koanf:"logger"`
Bespoke Customization `koanf:"bespoke"`
Perf Performance `koanf:"performance"`
Liar Deception `koanf:"deception"`

IdleHands DevilsPlaythings `koanf:"experimental"`

Expand Down
33 changes: 25 additions & 8 deletions internal/config/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
flags "github.com/knadh/koanf/providers/basicflag"
"github.com/knadh/koanf/providers/env"
"github.com/knadh/koanf/v2"

"github.com/yunginnanet/HellPot/internal/logger"
)

type readerProvider struct {
Expand Down Expand Up @@ -67,17 +69,21 @@ func (p *Parameters) merge(ogk *koanf.Koanf, newk *koanf.Koanf, friendlyName str
return nil
}

for k, v := range newKeys {
if !ogk.Exists(k) {
if err := ogk.Set(k, v); err != nil {
panic(fmt.Sprintf("failed to set key %s: %v", k, err))
}
dirty = true
continue
valIsEmpty := func(v any) bool {
switch v.(type) {
case string:
return v.(string) == ""
case []string:
return len(v.([]string)) == 0
default:
return false
}
}

for k, v := range newKeys {
ogv := ogk.Get(k)
if ogv == nil {
if ogk.Exists(k) && valIsEmpty(ogv) && !valIsEmpty(v) {
println("setting newer value for key " + k + " to " + fmt.Sprintf("%v", v) + " from " + friendlyName)
if err := ogk.Set(k, v); err != nil {
panic(fmt.Sprintf("failed to set key %s: %v", k, err))
}
Expand Down Expand Up @@ -189,5 +195,16 @@ func Setup(source io.Reader) (*Parameters, error) {
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
}

// for some reason the logger config pointer is not getting populated, do it manually
p.Logger = logger.Configuration{}
for k, v := range k.All() {
if strings.HasPrefix(k, "logger.") {
println("setting logger config key " + k + " to " + fmt.Sprintf("%v", v))
if err := p.Logger.Set(k, v); err != nil {
return nil, fmt.Errorf("failed to set logger config: %w", err)
}
}
}

return p, nil
}
24 changes: 23 additions & 1 deletion internal/config/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
)

func TestSetup(t *testing.T) {
t.Setenv("HELLPOT_TEST_MODE", "true")
t.Run("Success", SetupSuccess)
t.Run("NoFailureOnNilSource", SetupNoFailureOnNilSource)
t.Run("FailureOnReadConfig", SetupFailureOnReadConfig)
Expand All @@ -20,6 +21,10 @@ bind_addr = "5.5.5.5"
[http.router]
catchall = true
makerobots = false
[logger]
debug = true
rsyslog_address = "local"
`)

params, err := Setup(source)
Expand Down Expand Up @@ -49,7 +54,24 @@ makerobots = false
if params.HTTP.Router.CatchAll != true {
t.Errorf("Expected true, got %v", params.HTTP.Router.CatchAll)
}

if params.source.Get("http.router.makerobots") != false {
t.Errorf("Expected false, got %v", params.source.Get("http.router.makerobots"))
}
if params.HTTP.Router.MakeRobots != false {
t.Errorf("Expected false, got %v", params.HTTP.Router.MakeRobots)
}
if params.source.Get("logger.debug") != true {
t.Errorf("Expected true, got %v", params.source.Get("logger.debug"))
}
if params.Logger.Debug != true {
t.Errorf("Expected true, got %v", params.Logger.Debug)
}
if params.source.Get("logger.rsyslog_address") != "local" {
t.Errorf("Expected local, got %v", params.source.Get("logger.rsyslog_address"))
}
if params.Logger.RSyslog != "local" {
t.Errorf("Expected local, got %v", params.Logger.RSyslog)
}
}

func SetupNoFailureOnNilSource(t *testing.T) {
Expand Down
Loading

0 comments on commit e31113b

Please sign in to comment.