Skip to content
Snippets Groups Projects
test_util_test.go 8.73 KiB
Newer Older
  • Learn to ignore specific revisions
  • package server
    
    import (
    	"bytes"
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	"encoding/base64"
    
    	"log"
    	"testing"
    
    
    	"code.fbi.h-da.de/danet/gosdn/controller/conflict"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/networkelement"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/plugin"
    
    	rbacInterfaces "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac"
    	"code.fbi.h-da.de/danet/gosdn/controller/mocks"
    
    
    	"code.fbi.h-da.de/danet/gosdn/controller/rbac"
    	"code.fbi.h-da.de/danet/gosdn/controller/store"
    	"github.com/google/uuid"
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	"github.com/sethvargo/go-password/password"
    	"golang.org/x/crypto/argon2"
    
    const pndID = "2043519e-46d1-4963-9a8e-d99007e104b8"
    
    const pluginID = "22ecbd5e-37de-43e3-be56-358f9716fd7d"
    
    const pendingChangeID = "0992d600-f7d4-4906-9559-409b04d59a5f"
    const committedChangeID = "804787d6-e5a8-4dba-a1e6-e73f96b0119e"
    
    const mneID = "7e0ed8cc-ebf5-46fa-9794-741494914883"
    
    var pendingChangeUUID uuid.UUID
    var committedChangeUUID uuid.UUID
    
    var mockPnd *mocks.NetworkDomain
    
    var mockNetworkElement networkelement.NetworkElement
    
    // 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"}
    
    
    func clearAndCreateAuthTestSetup(userService rbacInterfaces.UserService, roleService rbacInterfaces.RoleService) error {
    
    	//clear setup if changed
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	storedUsers, err := userService.GetAll()
    
    	if err != nil {
    		return err
    	}
    	for _, u := range storedUsers {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		err = userService.Delete(u)
    
    		if err != nil {
    			return err
    		}
    	}
    
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	storedRoles, err := roleService.GetAll()
    
    	if err != nil {
    		return err
    	}
    	for _, r := range storedRoles {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		err = roleService.Delete(r)
    
    		if err != nil {
    			return err
    		}
    	}
    
    	// create dataset
    
    	err = createTestUsers(userService)
    
    	if err != nil {
    		return err
    	}
    
    
    	err = createTestRoles(roleService)
    
    	if err != nil {
    		return err
    	}
    
    	return nil
    }
    
    
    func createTestUsers(userService rbacInterfaces.UserService) error {
    
    	randomRoleMap := map[string]string{pndID: randomRoleName}
    
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	// 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)
    
    
    	wrongTokens := []string{"Wrong token"}
    
    	users := []rbac.User{
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		{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, Tokens: wrongTokens},
    
    	wrongTokens = []string{}
    
    	for _, u := range users {
    
    		err := userService.Add(rbac.NewUser(u.ID(), u.Name(), u.Roles, u.Password, wrongTokens, salt, conflict.Metadata{ResourceVersion: 0}))
    
    		if err != nil {
    			return err
    		}
    	}
    
    	return nil
    }
    
    
    func createTestRoles(roleService rbacInterfaces.RoleService) 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.plugin_internal.PluginInternalService/GetPluginSchema",
    
    			},
    		},
    		{
    			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 {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		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. Apparently, 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, userService rbacInterfaces.UserService, jwt *rbac.JWTManager) (string, error) {
    
    	token, err := jwt.GenerateToken(rbac.User{UserName: userName})
    
    	tokens := []string{token}
    
    	if err != nil {
    		return token, err
    	}
    
    	if validTokenRequired {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		user, err := userService.Get(store.Query{Name: userName})
    
    		if err != nil {
    			return token, err
    		}
    
    		user.SetTokens(tokens)
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		err = userService.Update(user)
    
    		if err != nil {
    			return token, err
    		}
    	}
    
    	return token, nil
    }
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    
    func createHashedAndSaltedPassword(plainPWD, salt string) string {
    	return base64.RawStdEncoding.EncodeToString(argon2.IDKey([]byte(plainPWD), []byte(salt), 1, 64*1024, 4, 32))
    }
    
    // func getMockPnd(t *testing.T) networkdomain.NetworkDomain {
    // 	mockNetworkElement = &nucleus.CommonNetworkElement{
    // 		Plugin: &mocks.Plugin{},
    // 		UUID:   mneUUID,
    // 	}
    
    // 	mockNetworkElement.(*nucleus.CommonNetworkElement).SetTransport(&mocks.Transport{})
    // 	mockNetworkElement.(*nucleus.CommonNetworkElement).SetName(hostname)
    
    // 	mockPnd = &mocks.NetworkDomain{}
    // 	mockPnd.On("ID").Return(pndUUID)
    // 	mockPnd.On("GetName").Return("test")
    // 	mockPnd.On("GetDescription").Return("test")
    // 	mockPnd.On("NetworkElements").Return([]uuid.UUID{mneUUID})
    // 	mockPnd.On("PendingChanges").Return([]uuid.UUID{pendingChangeUUID})
    // 	mockPnd.On("CommittedChanges").Return([]uuid.UUID{committedChangeUUID})
    // 	mockPnd.On("AddNetworkElement", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
    // 	mockPnd.On("GetNetworkElement", mock.Anything).Return(mockNetworkElement, nil)
    // 	mockPnd.On("Commit", mock.Anything).Return(nil)
    // 	mockPnd.On("Confirm", mock.Anything).Return(nil)
    // 	mockPnd.On("ChangeMNE", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(uuid.Nil, nil)
    // 	mockPnd.On("Request", mock.Anything, mock.Anything).Return(nil, nil)
    
    // 	return mockPnd
    // }
    
    func getMockPlugin(t *testing.T) plugin.Plugin {
    	mockPlugin := &mocks.Plugin{}
    
    	mockPlugin.On("ID").Return(pluginUUID)
    	mockPlugin.On("SchemaTreeGzip").Return([]byte("schema_test"), nil)
    	return mockPlugin
    }
    
    
    func initUUIDs(t *testing.T) {
    	var err error
    	pndUUID, err = uuid.Parse(pndID)
    	if err != nil {
    		t.Fatal(err)
    	}
    
    
    	pluginUUID, err = uuid.Parse(pluginID)
    
    	if err != nil {
    		t.Fatal(err)
    	}
    
    	pendingChangeUUID, err = uuid.Parse(pendingChangeID)
    	if err != nil {
    		t.Fatal(err)
    	}
    
    	committedChangeUUID, err = uuid.Parse(committedChangeID)
    	if err != nil {
    		t.Fatal(err)
    	}
    
    
    	mneUUID, err = uuid.Parse(mneID)
    
    
    // func createTestNetworkElementServer(t *testing.T, mneServer *NetworkElementServer) {
    // 	initUUIDs(t)
    
    // 	eventService := eventservice.NewMockEventService()
    
    // 	pluginService := nucleus.NewPluginServiceMock()
    
    // 	pndStore := nucleus.NewPndStore(pluginService)
    // 	pndService := nucleus.NewPndService(pndStore)
    
    // 	mneStore := nucleus.NewNetworkElementStore()
    // 	mneService := nucleus.NewNetworkElementService(mneStore, pluginService, eventService)
    
    // 	changeStore := store.NewChangeStore()
    
    // 	*mneServer = *NewNetworkElementServer(mneService, pndService, pluginService, *changeStore)
    
    // 	//t.Cleanup(removeTestStores)
    // }
    
    // func removeTestStores() {
    // 	ex, err := os.Executable()
    // 	if err != nil {
    // 		log.Println(err)
    // 	}
    // 	exPath := filepath.Dir(ex)
    
    // 	fmt.Println(exPath)
    
    // 	err = os.RemoveAll(exPath + "/stores_testing")
    // 	if err != nil {
    // 		log.Println(err)
    // 	}
    // }
    
    // func cleanMneAndSbiTestStore(mneServer *NetworkElementServer) {
    // 	mneToDelete, _ := mneServer.mneService.GetAll()
    // 	for _, mne := range mneToDelete {
    // 		_ = mneServer.mneService.Delete(mne)
    // 	}
    // }
    
    
    func stringToPointer(str string) *string {
    	return &str
    }