diff --git a/cmd/reset-admin-password/main.go b/cmd/reset-admin-password/main.go index a5cfb55..292ba27 100644 --- a/cmd/reset-admin-password/main.go +++ b/cmd/reset-admin-password/main.go @@ -11,6 +11,8 @@ import ( "syscall" "github.com/in4it/wireguard-server/pkg/commands" + localstorage "github.com/in4it/wireguard-server/pkg/storage/local" + "golang.org/x/term" ) @@ -23,8 +25,14 @@ func main() { flag.StringVar(&appDir, "vpn-dir", "/vpn", "directory where vpn files are located") flag.Parse() + localstorage, err := localstorage.NewWithPath(appDir) + if err != nil { + fmt.Printf("Failed to intialize storage: %s", err) + os.Exit(1) + } + password, _ := getPassword() - if newAdminUserCreated, err = commands.ResetPassword(appDir, password); err != nil { + if newAdminUserCreated, err = commands.ResetPassword(localstorage, password); err != nil { fmt.Printf("Failed to changed admin password: %s", err) os.Exit(1) } @@ -35,7 +43,7 @@ func main() { os.Exit(1) } if strings.TrimSpace(strings.ToUpper(resetMFA)) == "" || strings.TrimSpace(strings.ToUpper(resetMFA)) == "Y" { - err = commands.ResetAdminMFA(appDir) + err = commands.ResetAdminMFA(localstorage) if err != nil { fmt.Printf("Failed to reset admin MFA: %s", err) os.Exit(1) diff --git a/pkg/commands/resetmfa.go b/pkg/commands/resetmfa.go index d3e7dca..5de910a 100644 --- a/pkg/commands/resetmfa.go +++ b/pkg/commands/resetmfa.go @@ -4,20 +4,16 @@ import ( "fmt" "github.com/in4it/wireguard-server/pkg/rest" - localstorage "github.com/in4it/wireguard-server/pkg/storage/local" + "github.com/in4it/wireguard-server/pkg/storage" "github.com/in4it/wireguard-server/pkg/users" ) -func ResetAdminMFA(appDir string) error { - localstorage, err := localstorage.NewWithPath(appDir) +func ResetAdminMFA(storage storage.Iface) error { + c, err := rest.GetConfig(storage) if err != nil { return fmt.Errorf("config retrieval error: %s", err) } - c, err := rest.GetConfig(localstorage) - if err != nil { - return fmt.Errorf("config retrieval error: %s", err) - } - c.UserStore, err = users.NewUserStore(localstorage, -1) + c.UserStore, err = users.NewUserStore(storage, -1) if err != nil { return fmt.Errorf("userstore initialization error: %s", err) } diff --git a/pkg/commands/resetpassword.go b/pkg/commands/resetpassword.go index fbef43e..2e5efa2 100644 --- a/pkg/commands/resetpassword.go +++ b/pkg/commands/resetpassword.go @@ -4,26 +4,21 @@ import ( "fmt" "github.com/in4it/wireguard-server/pkg/rest" - localstorage "github.com/in4it/wireguard-server/pkg/storage/local" + "github.com/in4it/wireguard-server/pkg/storage" "github.com/in4it/wireguard-server/pkg/users" ) -func ResetPassword(appDir, password string) (bool, error) { +func ResetPassword(storage storage.Iface, password string) (bool, error) { adminCreated := false - localstorage, err := localstorage.NewWithPath(appDir) - if err != nil { - return adminCreated, fmt.Errorf("config retrieval error: %s", err) - } - - c, err := rest.GetConfig(localstorage) + c, err := rest.GetConfig(storage) if err != nil { return adminCreated, fmt.Errorf("config retrieval error: %s", err) } c.Storage = &rest.Storage{ - Client: localstorage, + Client: storage, } - c.UserStore, err = users.NewUserStore(localstorage, -1) + c.UserStore, err = users.NewUserStore(storage, -1) if err != nil { return adminCreated, fmt.Errorf("userstore initialization error: %s", err) } diff --git a/pkg/commands/resetpassword_test.go b/pkg/commands/resetpassword_test.go new file mode 100644 index 0000000..45972fa --- /dev/null +++ b/pkg/commands/resetpassword_test.go @@ -0,0 +1,101 @@ +package commands + +import ( + "testing" + + memorystorage "github.com/in4it/wireguard-server/pkg/storage/memory" + "github.com/in4it/wireguard-server/pkg/users" +) + +func TestResetPassword(t *testing.T) { + storage := &memorystorage.MockMemoryStorage{} + adminCreated, err := ResetPassword(storage, "mytestpassword") + if err != nil { + t.Fatalf("reset password error: %s", err) + } + if !adminCreated { + t.Fatalf("expected newly user to be created, received an userdatabase update instead") + } + userStore, err := users.NewUserStore(storage, -1) + if err != nil { + t.Fatalf("userstore initialization error: %s", err) + } + user, err := userStore.GetUserByLogin("admin") + if err != nil { + t.Fatalf("get user by loginerror: %s", err) + } + if user.Login != "admin" { + t.Fatalf("retrieved user is not admin") + } + if _, authOK := userStore.AuthUser("admin", "mytestpassword"); !authOK { + t.Fatalf("couldn't authenticate admin") + } +} +func TestResetPasswordExistingAdmin(t *testing.T) { + storage := &memorystorage.MockMemoryStorage{} + userStore, err := users.NewUserStore(storage, -1) + if err != nil { + t.Fatalf("userstore initialization error: %s", err) + } + _, err = userStore.AddUser(users.User{ID: "1-2-3-4", Login: "admin", Role: "admin"}) + if err != nil { + t.Fatalf("could not add user: %s", err) + } + + adminCreated, err := ResetPassword(storage, "mytestpassword") + if err != nil { + t.Fatalf("reset password error: %s", err) + } + if adminCreated { + t.Fatalf("expected admin user to already exist") + } + userStore, err = users.NewUserStore(storage, -1) // user store is not in sync anymore with the file + if err != nil { + t.Fatalf("userstore initialization error: %s", err) + } + if _, authOK := userStore.AuthUser("admin", "mytestpassword"); !authOK { + t.Fatalf("couldn't authenticate admin") + } +} + +func TestResetPasswordExistingAdminResetMFA(t *testing.T) { + storage := &memorystorage.MockMemoryStorage{} + userStore, err := users.NewUserStore(storage, -1) + if err != nil { + t.Fatalf("userstore initialization error: %s", err) + } + factors := []users.Factor{ + { + Name: "google", + Type: "otp", + Secret: "123456", + }, + } + _, err = userStore.AddUser(users.User{ID: "1-2-3-4", Login: "admin", Role: "admin", Factors: factors}) + if err != nil { + t.Fatalf("could not add user: %s", err) + } + + adminCreated, err := ResetPassword(storage, "mytestpassword") + if err != nil { + t.Fatalf("reset password error: %s", err) + } + if adminCreated { + t.Fatalf("expected admin user to already exist") + } + err = ResetAdminMFA(storage) + if err != nil { + t.Fatalf("reset admin mfa error: %s", err) + } + userStore, err = users.NewUserStore(storage, -1) // user store is not in sync anymore with the file + if err != nil { + t.Fatalf("userstore initialization error: %s", err) + } + user, err := userStore.GetUserByLogin("admin") + if err != nil { + t.Fatalf("get user by login error: %s", err) + } + if len(user.Factors) > 0 { + t.Fatalf("found MFA for admin user") + } +}