From bef52d36f197a7bd7e999bf1ebea93d24399d490 Mon Sep 17 00:00:00 2001 From: Jordan Wright Date: Sat, 6 Oct 2018 15:47:31 -0500 Subject: [PATCH] Adding ability to log to file as well as stderr. Fixes #441. Fixes #1209. --- config.json | 3 +- config/config.go | 21 +++++-------- config/config_test.go | 68 +++++++++++++++++++++++++++++++++++++++++++ gophish.go | 15 +++++++++- logger/logger.go | 19 +++++++++++- 5 files changed, 110 insertions(+), 16 deletions(-) create mode 100644 config/config_test.go diff --git a/config.json b/config.json index e05eade4..5b81b68c 100644 --- a/config.json +++ b/config.json @@ -14,5 +14,6 @@ "db_name": "sqlite3", "db_path": "gophish.db", "migrations_prefix": "db/db_", - "contact_address": "" + "contact_address": "", + "log_file": "" } \ No newline at end of file diff --git a/config/config.go b/config/config.go index 53165a64..efac36c1 100644 --- a/config/config.go +++ b/config/config.go @@ -3,8 +3,6 @@ package config import ( "encoding/json" "io/ioutil" - - log "github.com/gophish/gophish/logger" ) // AdminServer represents the Admin server configuration details @@ -32,6 +30,7 @@ type Config struct { MigrationsPath string `json:"migrations_prefix"` TestFlag bool `json:"test_flag"` ContactAddress string `json:"contact_address"` + LogFile string `json:"log_file"` } // Conf contains the initialized configuration struct @@ -44,23 +43,19 @@ var Version = "" const ServerName = "gophish" // LoadConfig loads the configuration from the specified filepath -func LoadConfig(filepath string) { +func LoadConfig(filepath string) error { // Get the config file configFile, err := ioutil.ReadFile(filepath) if err != nil { - log.Errorf("File error: %v\n", err) + return err + } + err = json.Unmarshal(configFile, &Conf) + if err != nil { + return err } - json.Unmarshal(configFile, &Conf) - // Choosing the migrations directory based on the database used. Conf.MigrationsPath = Conf.MigrationsPath + Conf.DBName // Explicitly set the TestFlag to false to prevent config.json overrides Conf.TestFlag = false - - // Print a warning if a contact address isn't provided - // (see: https://github.com/gophish/gophish/issues/1057) - if Conf.ContactAddress == "" { - log.Warnf("No contact address has been configured.") - log.Warnf("Please consider adding a contact_address entry in your config.json") - } + return nil } diff --git a/config/config_test.go b/config/config_test.go new file mode 100644 index 00000000..7e16b81a --- /dev/null +++ b/config/config_test.go @@ -0,0 +1,68 @@ +package config + +import ( + "encoding/json" + "io/ioutil" + "os" + "testing" + + "github.com/stretchr/testify/suite" +) + +type ConfigSuite struct { + suite.Suite + ConfigFile *os.File +} + +var validConfig = []byte(`{ + "admin_server": { + "listen_url": "127.0.0.1:3333", + "use_tls": true, + "cert_path": "gophish_admin.crt", + "key_path": "gophish_admin.key" + }, + "phish_server": { + "listen_url": "0.0.0.0:8080", + "use_tls": false, + "cert_path": "example.crt", + "key_path": "example.key" + }, + "db_name": "sqlite3", + "db_path": "gophish.db", + "migrations_prefix": "db/db_", + "contact_address": "" +}`) + +func (s *ConfigSuite) SetupTest() { + f, err := ioutil.TempFile("", "gophish-config") + s.Nil(err) + s.ConfigFile = f +} + +func (s *ConfigSuite) TearDownTest() { + err := s.ConfigFile.Close() + s.Nil(err) +} + +func (s *ConfigSuite) TestLoadConfig() { + _, err := s.ConfigFile.Write(validConfig) + s.Nil(err) + // Load the valid config + err = LoadConfig(s.ConfigFile.Name()) + s.Nil(err) + + expectedConfig := Config{} + err = json.Unmarshal(validConfig, &expectedConfig) + s.Nil(err) + expectedConfig.MigrationsPath = expectedConfig.MigrationsPath + expectedConfig.DBName + expectedConfig.TestFlag = false + s.Equal(expectedConfig, Conf) + + // Load an invalid config + err = LoadConfig("bogusfile") + s.NotNil(err) +} + +func TestConfigSuite(t *testing.T) { + suite.Run(t, new(ConfigSuite)) +} diff --git a/gophish.go b/gophish.go index 2df7933a..514323ab 100644 --- a/gophish.go +++ b/gophish.go @@ -65,9 +65,22 @@ func main() { kingpin.Parse() // Load the config - config.LoadConfig(*configPath) + err = config.LoadConfig(*configPath) + // Just warn if a contact address hasn't been configured + if err != nil { + log.Fatal(err) + } + if config.Conf.ContactAddress == "" { + log.Warnf("No contact address has been configured.") + log.Warnf("Please consider adding a contact_address entry in your config.json") + } config.Version = string(version) + err = log.Setup() + if err != nil { + log.Fatal(err) + } + ctx, cancel := context.WithCancel(context.Background()) defer cancel() diff --git a/logger/logger.go b/logger/logger.go index ba8372da..4fe9c262 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -2,7 +2,9 @@ package logger import ( "io" + "os" + "github.com/gophish/gophish/config" "github.com/sirupsen/logrus" ) @@ -12,10 +14,25 @@ var Logger *logrus.Logger func init() { Logger = logrus.New() - Logger.SetLevel(logrus.InfoLevel) Logger.Formatter = &logrus.TextFormatter{DisableColors: true} } +// Setup configures the logger based on options in the config.json. +func Setup() error { + Logger.SetLevel(logrus.InfoLevel) + // Set up logging to a file if specified in the config + logFile := config.Conf.LogFile + if logFile != "" { + f, err := os.OpenFile(logFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) + if err != nil { + return err + } + mw := io.MultiWriter(os.Stderr, f) + Logger.Out = mw + } + return nil +} + func Debug(args ...interface{}) { Logger.Debug(args...) }