HellPot/config/config.go

299 lines
7.0 KiB
Go
Raw Normal View History

package config
import (
"bytes"
"fmt"
"io/ioutil"
"os"
2021-09-15 14:04:16 +00:00
"runtime"
"github.com/rs/zerolog"
"github.com/spf13/viper"
)
const (
2021-09-16 07:51:16 +00:00
// Version roughly represents the applications current version.
2021-09-15 14:04:16 +00:00
Version = "0.3"
2021-09-16 07:51:16 +00:00
// Title is the name of the application used throughout the configuration process.
2021-09-15 14:04:16 +00:00
Title = "HellPot"
)
2021-09-16 07:51:16 +00:00
var (
// BannerOnly when toggled causes HellPot to only print the banner and version then exit.
BannerOnly = false
// ConfigGen when toggled causes HellPot to write its default config to the cwd and then exit.
ConfigGen = false
)
2021-09-15 19:17:32 +00:00
2021-09-15 16:13:16 +00:00
// "http"
var (
// BindAddr is defined via our toml configuration file. It is the address that HellPot listens on.
BindAddr string
// BindPort is defined via our toml configuration file. It is the port that HellPot listens on.
BindPort string
// Paths are defined via our toml configuration file. These are the paths that HellPot will present for "robots.txt"
// These are also the paths that HellPot will respond for. Other paths will throw a warning and will serve a 404.
Paths []string
2021-09-15 16:13:16 +00:00
2021-09-16 07:51:16 +00:00
// UseUnixSocket when toggled disables the TCP listener and listens on the given UnixSocketPath.
2021-09-15 16:13:16 +00:00
UseUnixSocket bool
2021-09-16 07:51:16 +00:00
// UnixSocketPath is the path of the unix socket used when UseUnixSocket is toggled.
2021-09-15 16:13:16 +00:00
UnixSocketPath = ""
)
// "performance"
var (
RestrictConcurrency bool
2021-09-15 19:17:32 +00:00
MaxWorkers int
2021-09-15 16:13:16 +00:00
)
2021-09-15 19:55:48 +00:00
// "deception"
2021-09-15 16:13:16 +00:00
var (
// FakeServerName is our configured value for the "Server: " response header when serving HTTP clients
FakeServerName string
)
var (
// Filename returns the current location of our toml config file.
Filename string
)
var (
f *os.File
err error
2021-09-15 19:33:42 +00:00
NoColorForce = false
2021-09-15 14:04:16 +00:00
NoColor bool
customconfig = false
home string
configLocations []string
)
/*
Opt represents our program options.
nitially the values that are defined in Opt will be used to define details.
Beyond that, default values will be replaced by options from our config file.
*/
var Opt map[string]map[string]interface{}
var (
// Debug is our global debug toggle
Debug bool
prefConfigLocation string
snek *viper.Viper
)
func init() {
if home, err = os.UserHomeDir(); err != nil {
panic(err)
}
2021-09-15 14:04:16 +00:00
prefConfigLocation = home + "/.config/" + Title
Opt = make(map[string]map[string]interface{})
snek = viper.New()
}
// Init will initialize our toml configuration engine and define our default configuration values which can be written to a new configuration file if desired
func Init() {
snek.SetConfigType("toml")
snek.SetConfigName("config")
argParse()
if customconfig {
associate()
return
}
acquireClue()
setDefaults()
for _, loc := range configLocations {
snek.AddConfigPath(loc)
}
2021-09-15 14:04:16 +00:00
if err = snek.MergeInConfig(); err != nil && runtime.GOOS != "windows" {
if _, err := os.Stat(prefConfigLocation); os.IsNotExist(err) {
if err = os.Mkdir(prefConfigLocation, 0755); err != nil {
2021-09-15 13:43:01 +00:00
println("error writing new config: " + err.Error())
}
}
2021-09-15 14:04:16 +00:00
newconfig := prefConfigLocation + "/" + "config.toml"
if err = snek.SafeWriteConfigAs(newconfig); err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
2021-09-15 14:04:16 +00:00
Filename = newconfig
}
2021-09-15 14:04:16 +00:00
if runtime.GOOS == "windows" {
newconfig := "hellpot-config"
snek.SetConfigName(newconfig)
if err = snek.MergeInConfig(); err != nil {
if err = snek.SafeWriteConfigAs(newconfig + ".toml"); err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
}
Filename = newconfig
}
if len(Filename) < 1 {
Filename = snek.ConfigFileUsed()
}
associate()
}
func setDefaults() {
2021-09-15 14:04:16 +00:00
var (
2021-09-15 19:55:48 +00:00
configSections = []string{"logger", "http", "performance", "deception"}
2021-09-15 14:04:16 +00:00
deflogdir = home + "/.config/" + Title + "/logs/"
defNoColor = false
)
if runtime.GOOS == "windows" {
deflogdir = "logs/"
defNoColor = true
}
Opt["logger"] = map[string]interface{}{
2021-09-15 14:04:16 +00:00
"debug": true,
"directory": deflogdir,
"nocolor": defNoColor,
"use_date_filename": true,
}
Opt["http"] = map[string]interface{}{
2021-09-15 19:33:42 +00:00
"use_unix_socket": false,
"unix_socket_path": "/var/run/hellpot",
"bind_addr": "127.0.0.1",
"bind_port": "8080",
"paths": []string{
"wp-login.php",
"wp-login",
},
}
2021-09-15 16:13:16 +00:00
Opt["performance"] = map[string]interface{}{
"restrict_concurrency": false,
2021-09-15 19:17:32 +00:00
"max_workers": 256,
2021-09-15 16:13:16 +00:00
}
2021-09-15 19:55:48 +00:00
Opt["deception"] = map[string]interface{}{
2021-09-15 16:13:16 +00:00
"server_name": "nginx",
}
for _, def := range configSections {
snek.SetDefault(def, Opt[def])
}
2021-09-16 07:51:16 +00:00
if ConfigGen {
if err = snek.SafeWriteConfigAs("./config.toml"); err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
os.Exit(0)
}
}
func acquireClue() {
configLocations = append(configLocations, "./")
2021-09-15 14:04:16 +00:00
if runtime.GOOS != "windows" {
configLocations = append(configLocations, prefConfigLocation)
configLocations = append(configLocations, "/etc/"+Title+"/")
configLocations = append(configLocations, "../")
configLocations = append(configLocations, "../../")
}
}
func loadCustomConfig(path string) {
if f, err = os.Open(path); err != nil {
println("Error opening specified config file: " + path)
panic("config file open fatal error: " + err.Error())
}
buf, err := ioutil.ReadAll(f)
err2 := snek.ReadConfig(bytes.NewBuffer(buf))
switch {
case err != nil:
fmt.Println("config file read fatal error: ", err.Error())
case err2 != nil:
fmt.Println("config file read fatal error: ", err2.Error())
default:
break
}
customconfig = true
}
2021-09-16 07:51:16 +00:00
func printUsage() {
println("\n"+Title+" v"+Version+" Usage\n")
println("-c <config.toml> - Specify config file")
println("--nocolor - disable color and banner ")
println("--banner - show banner + version and exit")
println("--genconfig - write default config to 'default.toml' then exit")
os.Exit(0)
}
// TODO: should probably just make a proper CLI with flags or something
func argParse() {
for i, arg := range os.Args {
switch arg {
2021-09-15 14:04:16 +00:00
case "-h":
2021-09-16 07:51:16 +00:00
printUsage()
case "--genconfig":
ConfigGen = true
2021-09-15 19:33:42 +00:00
case "--nocolor":
NoColorForce = true
2021-09-15 19:17:32 +00:00
case "--banner":
BannerOnly = true
2021-09-15 19:33:42 +00:00
case "--config":
fallthrough
case "-c":
if len(os.Args) <= i-1 {
panic("syntax error! expected file after -c")
}
loadCustomConfig(os.Args[i+1])
default:
continue
}
}
}
func associate() {
var newOpt map[string]map[string]interface{}
newOpt = Opt
for category, opt := range Opt {
for optname, value := range opt {
if snek.IsSet(category + "." + optname) {
newOpt[category][optname] = value
}
}
}
Opt = newOpt
Debug = snek.GetBool("logger.debug")
logDir = snek.GetString("logger.directory")
BindAddr = snek.GetString("http.bind_addr")
BindPort = snek.GetString("http.bind_port")
Paths = snek.GetStringSlice("http.paths")
2021-09-15 16:13:16 +00:00
UseUnixSocket = snek.GetBool("http.use_unix_socket")
2021-09-15 19:55:48 +00:00
FakeServerName = snek.GetString("deception.server_name")
2021-09-15 16:13:16 +00:00
RestrictConcurrency = snek.GetBool("performance.restrict_concurrency")
MaxWorkers = snek.GetInt("performance.max_workers")
2021-09-15 19:33:42 +00:00
NoColor = snek.GetBool("logger.nocolor")
if NoColorForce {
NoColor = true
}
2021-09-15 16:13:16 +00:00
if UseUnixSocket {
UnixSocketPath = snek.GetString("http.unix_socket_path")
}
if Debug {
zerolog.SetGlobalLevel(zerolog.DebugLevel)
}
}