From d8c458fc6cbe1f8b73dc873c4870f3e3e1b9f61d Mon Sep 17 00:00:00 2001 From: Christian Claus Date: Wed, 11 Apr 2018 15:22:42 +0200 Subject: [PATCH] Add cli tool to generate BCrypt passwords --- app/config.go | 79 ++++++++++++++++++++++--------------- cmd/{server => swd}/main.go | 3 +- cmd/swdcli/main.go | 7 ++++ cmd/swdcli/subcmd/passwd.go | 51 ++++++++++++++++++++++++ cmd/swdcli/subcmd/root.go | 22 +++++++++++ 5 files changed, 130 insertions(+), 32 deletions(-) rename cmd/{server => swd}/main.go (94%) create mode 100644 cmd/swdcli/main.go create mode 100644 cmd/swdcli/subcmd/passwd.go create mode 100644 cmd/swdcli/subcmd/root.go diff --git a/app/config.go b/app/config.go index 622ca70..93ca499 100644 --- a/app/config.go +++ b/app/config.go @@ -2,10 +2,11 @@ package app import ( "fmt" + "github.com/fsnotify/fsnotify" "github.com/spf13/viper" "log" "os" - "github.com/fsnotify/fsnotify" + "path/filepath" ) // Config represents the configuration of the server application. @@ -59,37 +60,9 @@ func ParseConfig() *Config { } viper.WatchConfig() - viper.OnConfigChange(func(e fsnotify.Event) { - fmt.Println("Config file changed:", e.Name) + viper.OnConfigChange(cfg.updateConfig) - file, err := os.Open(e.Name) - if err != nil { - fmt.Println("Error reloading config", e.Name) - } - - var updatedCfg = &Config{} - viper.ReadConfig(file) - viper.Unmarshal(&updatedCfg) - - for k, _ := range cfg.Users { - if updatedCfg.Users[k] == nil { - fmt.Printf("Removed User from configuration: %s\n", k) - cfg.Users[k] = nil - } - } - - for k, v := range updatedCfg.Users { - if cfg.Users[k] == nil { - fmt.Printf("Added User to configuration: %s\n", k) - cfg.Users[k] = v - } else { - if cfg.Users[k].Password != v.Password { - fmt.Printf("Updated password of user: %s\n", k) - cfg.Users[k].Password = v.Password - } - } - } - }) + cfg.ensureUserDirs() return cfg } @@ -102,3 +75,47 @@ func setDefaults() { viper.SetDefault("Dir", "/tmp") viper.SetDefault("TLS", nil) } + +func (cfg *Config) updateConfig(e fsnotify.Event) { + fmt.Println("Config file changed:", e.Name) + + file, err := os.Open(e.Name) + if err != nil { + fmt.Println("Error reloading config", e.Name) + } + + var updatedCfg = &Config{} + viper.ReadConfig(file) + viper.Unmarshal(&updatedCfg) + + for username := range cfg.Users { + if updatedCfg.Users[username] == nil { + fmt.Printf("Removed User from configuration: %s\n", username) + cfg.Users[username] = nil + } + } + + for username, v := range updatedCfg.Users { + if cfg.Users[username] == nil { + fmt.Printf("Added User to configuration: %s\n", username) + cfg.Users[username] = v + } else { + if cfg.Users[username].Password != v.Password { + fmt.Printf("Updated password of user: %s\n", username) + cfg.Users[username].Password = v.Password + } + } + } + + cfg.ensureUserDirs() +} + +func (cfg *Config) ensureUserDirs() { + for username := range cfg.Users { + path := filepath.Join(cfg.Dir, username) + if _, err := os.Stat(path); os.IsNotExist(err) { + os.Mkdir(path, os.ModePerm) + fmt.Printf("Created user dir: %s\n", path) + } + } +} diff --git a/cmd/server/main.go b/cmd/swd/main.go similarity index 94% rename from cmd/server/main.go rename to cmd/swd/main.go index 4b74fa8..f777f22 100644 --- a/cmd/server/main.go +++ b/cmd/swd/main.go @@ -17,9 +17,10 @@ func main() { BaseDir: config.Dir, }, LockSystem: webdav.NewMemLS(), - Logger: app.ModificationLogHandler, } + wdHandler.Logger = app.ModificationLogHandler + a := &app.App{ Config: config, Handler: wdHandler, diff --git a/cmd/swdcli/main.go b/cmd/swdcli/main.go new file mode 100644 index 0000000..d0bd7a0 --- /dev/null +++ b/cmd/swdcli/main.go @@ -0,0 +1,7 @@ +package main + +import "github.com/micromata/swd/cmd/swdcli/subcmd" + +func main() { + subcmd.Execute() +} diff --git a/cmd/swdcli/subcmd/passwd.go b/cmd/swdcli/subcmd/passwd.go new file mode 100644 index 0000000..81dd77a --- /dev/null +++ b/cmd/swdcli/subcmd/passwd.go @@ -0,0 +1,51 @@ +package subcmd + +import ( + "fmt" + "github.com/spf13/cobra" + "golang.org/x/crypto/bcrypt" + "golang.org/x/crypto/ssh/terminal" + "log" + "os" + "syscall" +) + +var passwdCmd = &cobra.Command{ + Use: "passwd", + Short: "Generates a BCrypt hash of a given input string", + Run: func(cmd *cobra.Command, args []string) { + pw1 := readPassword() + pw2 := readPassword() + + pw1Str := string(pw1) + pw2Str := string(pw2) + + if pw1Str != pw2Str { + fmt.Println("Passwords doesn't match.") + os.Exit(1) + } + + pw, err := bcrypt.GenerateFromPassword(pw1, 10) + if err != nil { + log.Fatal(err) + } + + fmt.Printf("Hashed Password: %s\n", string(pw)) + }, +} + +func readPassword() []byte { + fmt.Print("Enter password: ") + pw, err := terminal.ReadPassword(int(syscall.Stdin)) + if err != nil { + fmt.Printf("An error occurred reading the password: %s\n", err) + os.Exit(1) + } + + fmt.Println() + return pw +} + +func init() { + RootCmd.AddCommand(passwdCmd) +} diff --git a/cmd/swdcli/subcmd/root.go b/cmd/swdcli/subcmd/root.go new file mode 100644 index 0000000..000497b --- /dev/null +++ b/cmd/swdcli/subcmd/root.go @@ -0,0 +1,22 @@ +package subcmd + +import ( + "fmt" + "github.com/spf13/cobra" + "os" +) + +// RootCmd represents the base command when called without any subcommands +var RootCmd = &cobra.Command{ + Use: "swdcli", + Short: "A cli for the simple webdav server", +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + if err := RootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +}