package server import ( "bytes" "encoding/base64" "log" "testing" "code.fbi.h-da.de/danet/gosdn/controller/rbac" "code.fbi.h-da.de/danet/gosdn/controller/store" "github.com/google/uuid" "github.com/sethvargo/go-password/password" "golang.org/x/crypto/argon2" ) // Name of this file requires _test at the end, because of how the availability of varibales is handled in test files of go packages. // Does not include actual file tests! const adminID = "5c248a22-8eb7-48cf-b392-45680a1863a5" const userID = "57005d13-7a4d-493d-a02b-50ca51c40197" const adminRoleID = "126683ae-5ff2-43ee-92f7-0e2b936f8c77" const randomRoleName = "bertram" var adminRoleMap = map[string]string{pndID: "adminTestRole"} var userRoleMap = map[string]string{pndID: "userTestRole"} var jwt *rbac.JWTManager func clearAndCreateAuthTestSetup() error { //clear setup if changed storedUsers, err := userService.GetAll() if err != nil { return err } for _, u := range storedUsers { err = userService.Delete(u) if err != nil { return err } } storedRoles, err := roleService.GetAll() if err != nil { return err } for _, r := range storedRoles { err = roleService.Delete(r) if err != nil { return err } } // create dataset err = createTestUsers() if err != nil { return err } err = createTestRoles() if err != nil { return err } return nil } func createTestUsers() error { randomRoleMap := map[string]string{pndID: randomRoleName} // Generate a salt that is 16 characters long with 3 digits, 0 symbols, // allowing upper and lower case letters, disallowing repeat characters. salt, err := password.Generate(16, 3, 0, true, false) if err != nil { return err } testAdminPWD := createHashedAndSaltedPassword("admin", salt) testUserPWD := createHashedAndSaltedPassword("user", salt) testRandPWD := createHashedAndSaltedPassword("aurelius", salt) users := []rbac.User{ {UserID: uuid.MustParse(adminID), UserName: "testAdmin", Roles: adminRoleMap, Password: testAdminPWD}, {UserID: uuid.MustParse(userID), UserName: "testUser", Roles: userRoleMap, Password: testUserPWD}, {UserID: uuid.New(), UserName: "testRandom", Roles: randomRoleMap, Password: testRandPWD, Token: "wrong token"}, } for _, u := range users { err := userService.Add(rbac.NewUser(u.ID(), u.Name(), u.Roles, u.Password, "", salt)) if err != nil { return err } } return nil } func createTestRoles() error { roles := []rbac.Role{ { RoleID: uuid.MustParse(adminRoleID), RoleName: "adminTestRole", Description: "Admin", Permissions: []string{ "/gosdn.core.CoreService/GetPnd", "/gosdn.core.CoreService/GetPndList", "/gosdn.rbac.UserService/GetUsers", "/gosdn.southbound.SbiService/GetSchema", }, }, { RoleID: uuid.New(), RoleName: "userTestRole", Description: "User", Permissions: []string{ "/gosdn.pnd.PndService/GetChangeList", }, }, { RoleID: uuid.New(), RoleName: randomRoleName, Description: "Not a role", Permissions: []string{ "nope", }, }, } for _, r := range roles { err := roleService.Add(rbac.NewRole(r.ID(), r.Name(), r.Description, r.Permissions)) if err != nil { return err } } return nil } // This is needed as a workaround for a bug where the output of the getUser test falsely was // that it failed while actually passing. Apparantely, this can happen when loggers write // the output of test cases. // Solution found here: https://github.com/gotestyourself/gotestsum/issues/141#issuecomment-686243110 func patchLogger(t *testing.T) { orig := log.Writer() buf := new(bytes.Buffer) log.SetOutput(buf) t.Cleanup(func() { // optionally check t.Failed here if you only want to print logs on failure t.Log(buf.String()) log.SetOutput(orig) }) } // Creates a token to be used in auth interceptor tests. If validTokenRequired is set as true, the generated token will also // be attached to the provided user. Else the user won't have the token and can not be authorized. func createTestUserToken(userName string, validTokenRequired bool) (string, error) { token, err := jwt.GenerateToken(rbac.User{UserName: userName}) if err != nil { return token, err } if validTokenRequired { user, err := userService.Get(store.Query{Name: userName}) if err != nil { return token, err } user.SetToken(token) err = userService.Update(user) if err != nil { return token, err } } return token, nil } func createHashedAndSaltedPassword(plainPWD, salt string) string { return base64.RawStdEncoding.EncodeToString(argon2.IDKey([]byte(plainPWD), []byte(salt), 1, 64*1024, 4, 32)) }