servewaf's and rproxy's settings are read through viper, bound to the same environment variable names as before, in place of the os.LookupEnv function Main passed down. NewViper turns AutomaticEnv and AllowEmptyEnv on, so a setting that is set but empty reads as set, as it did. A setting may also be given as a file, the _FILE form, which rproxy's settings now have too; rproxy still writes nothing to disk. The settings tests pass set into a viper instead of a lookup function. Model: deepseek-v4-pro
This commit is contained in:
1 parent
2e2f6f7175
commit
3fa1f4b732
19 files changed
+274
-185
No files matched your search
+41
-22
@@ -2,9 +2,8 @@
|
||||
// read. Every setting is an environment variable. The settings of `smallwebwaf
|
||||
// servewaf` start with SWWAF_, every one of them has a default, and most can be
|
||||
// given as a file instead. Those of `smallwebwaf rproxy` start with SWRP_. Each
|
||||
// of them but SWRP_WAF_BACKEND has a default, and none can be given as a file,
|
||||
// since rproxy never touches disk. SMALLWEBWAF_COMMAND chooses which of the two
|
||||
// the image runs.
|
||||
// of them but SWRP_WAF_BACKEND has a default, and each can be given as a file
|
||||
// too. SMALLWEBWAF_COMMAND chooses which of the two the image runs.
|
||||
package config
|
||||
|
||||
import (
|
||||
@@ -26,6 +25,8 @@ import (
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"sneak.berlin/go/smallwebwaf/internal/alerts"
|
||||
"sneak.berlin/go/smallwebwaf/internal/anomaly"
|
||||
"sneak.berlin/go/smallwebwaf/internal/remotelog"
|
||||
@@ -453,15 +454,16 @@ var (
|
||||
"is in SWWAF_BLOCKLIST_URLS or is SWWAF_ASN_LIMIT_PERCENT_URL too")
|
||||
)
|
||||
|
||||
// FromEnvironment reads the settings with lookupEnv, normally
|
||||
// os.LookupEnv. A setting may instead be given as a file: the variable
|
||||
// named by the setting's name with _FILE added names the file, which is
|
||||
// read now (see lookup). A setting that is not set takes its default. A
|
||||
// setting that is set but invalid is an error that names it.
|
||||
// FromEnvironment reads the settings through v, normally the viper
|
||||
// NewViper returns, bound to the process's environment. A setting may
|
||||
// instead be given as a file: the variable named by the setting's name
|
||||
// with _FILE added names the file, which is read now (see lookup). A
|
||||
// setting that is not set takes its default. A setting that is set but
|
||||
// invalid is an error that names it.
|
||||
//
|
||||
//nolint:funlen // one line for each setting, a list that grows with them
|
||||
func FromEnvironment(lookupEnv func(string) (string, bool)) (*Config, error) {
|
||||
env := &environment{lookupEnv: lookupEnv}
|
||||
func FromEnvironment(v *viper.Viper) (*Config, error) {
|
||||
env := &environment{v: v, readFiles: true}
|
||||
cfg := &Config{
|
||||
ListenAddr: env.address("SWWAF_LISTEN_ADDR"),
|
||||
InstanceName: env.instanceName(),
|
||||
@@ -580,8 +582,8 @@ func FromEnvironment(lookupEnv func(string) (string, bool)) (*Config, error) {
|
||||
// Command reads only SMALLWEBWAF_COMMAND, the command the image runs and its
|
||||
// health check checks: rproxy when it is unset or empty, or servewaf. It cannot
|
||||
// be given as a file. Any other value is an error that names the setting.
|
||||
func Command(lookupEnv func(string) (string, bool)) (string, error) {
|
||||
command, _ := lookupEnv("SMALLWEBWAF_COMMAND")
|
||||
func Command(v *viper.Viper) (string, error) {
|
||||
command, _ := readSetting(v, "SMALLWEBWAF_COMMAND")
|
||||
|
||||
switch command {
|
||||
case "", "rproxy":
|
||||
@@ -596,8 +598,8 @@ func Command(lookupEnv func(string) (string, bool)) (string, error) {
|
||||
// ServeWAFListenAddr reads only SWWAF_LISTEN_ADDR, which may be given as a
|
||||
// file, as FromEnvironment does. The health check in servewaf's container needs
|
||||
// no other setting, so it reads no other, nor a file that another names.
|
||||
func ServeWAFListenAddr(lookupEnv func(string) (string, bool)) (string, error) {
|
||||
env := &environment{lookupEnv: lookupEnv}
|
||||
func ServeWAFListenAddr(v *viper.Viper) (string, error) {
|
||||
env := &environment{v: v, readFiles: true}
|
||||
listenAddr := env.address("SWWAF_LISTEN_ADDR")
|
||||
|
||||
return listenAddr, env.err
|
||||
@@ -607,8 +609,8 @@ func ServeWAFListenAddr(lookupEnv func(string) (string, bool)) (string, error) {
|
||||
// file, as FromEnvironment does, so that the line saying a setting is
|
||||
// invalid carries it too. A file that cannot be read gives the default
|
||||
// here, and FromEnvironment then stops the start over it.
|
||||
func InstanceName(lookupEnv func(string) (string, bool)) string {
|
||||
env := &environment{lookupEnv: lookupEnv}
|
||||
func InstanceName(v *viper.Viper) string {
|
||||
env := &environment{v: v, readFiles: true}
|
||||
|
||||
return env.instanceName()
|
||||
}
|
||||
@@ -624,13 +626,26 @@ func (c *Config) LogValue() slog.Value {
|
||||
}
|
||||
|
||||
// environment is where FromEnvironment reads the settings: it notes each
|
||||
// value for the log, and keeps the first error.
|
||||
// value for the log, and keeps the first error. It reads every setting
|
||||
// through v, the viper NewViper returns, and, unless readFiles is false,
|
||||
// honours each setting's _FILE form too.
|
||||
type environment struct {
|
||||
lookupEnv func(string) (string, bool)
|
||||
v *viper.Viper
|
||||
readFiles bool
|
||||
settings []slog.Attr
|
||||
err error
|
||||
}
|
||||
|
||||
// readSetting returns a setting's value and whether it is set, reading it
|
||||
// through v.
|
||||
func readSetting(v *viper.Viper, name string) (string, bool) {
|
||||
if !v.IsSet(name) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
return v.GetString(name), true
|
||||
}
|
||||
|
||||
// value returns a setting's value, or its default when it is not set,
|
||||
// and notes it for the log.
|
||||
func (e *environment) value(name, defaultValue string) string {
|
||||
@@ -649,10 +664,14 @@ func (e *environment) value(name, defaultValue string) string {
|
||||
// names, less one newline at their end. It notes that file's path for the
|
||||
// log. Both variables set, or a file that cannot be read, is an error.
|
||||
func (e *environment) lookup(name string) (string, bool) {
|
||||
value, set := e.lookupEnv(name)
|
||||
value, set := readSetting(e.v, name)
|
||||
if !e.readFiles {
|
||||
return value, set
|
||||
}
|
||||
|
||||
fileName := name + "_FILE"
|
||||
|
||||
path, inFile := e.lookupEnv(fileName)
|
||||
path, inFile := readSetting(e.v, fileName)
|
||||
if !inFile {
|
||||
return value, set
|
||||
}
|
||||
@@ -1198,7 +1217,7 @@ func (e *environment) logRemoteURL(name string) *url.URL {
|
||||
// unset. Its value names a file already, so, unlike the other settings,
|
||||
// it has no _FILE form. Whoever uses the file reads it.
|
||||
func (e *environment) filePath(name string) string {
|
||||
path, _ := e.lookupEnv(name)
|
||||
path, _ := readSetting(e.v, name)
|
||||
e.settings = append(e.settings, slog.String(name, path))
|
||||
|
||||
return path
|
||||
@@ -1208,7 +1227,7 @@ func (e *environment) filePath(name string) string {
|
||||
// certificates. Unset or empty, it is nil. Its value names a file
|
||||
// already, so, unlike the other settings, it has no _FILE form.
|
||||
func (e *environment) certificates(name string) *x509.CertPool {
|
||||
path, _ := e.lookupEnv(name)
|
||||
path, _ := readSetting(e.v, name)
|
||||
e.settings = append(e.settings, slog.String(name, path))
|
||||
|
||||
if path == "" {
|
||||
|
||||
Reference in new issue
Block a user