Skip to content
Snippets Groups Projects
Commit 10d6f42d authored by Fabian Seidl's avatar Fabian Seidl
Browse files

Resolve "Implement integration tests for RBAC"

See merge request !652
parent fcf28de9
No related branches found
No related tags found
1 merge request!652Resolve "Implement integration tests for RBAC"
Pipeline #176394 passed
......@@ -89,7 +89,7 @@ message CreateUsersResponse {
// GetUser
message GetUserRequest {
int64 timestamp = 1;
string name = 2 [(buf.validate.field).required = true];
string name = 2 [(buf.validate.field).required = true]; // TODO(faseid): reconsider if this is necessary as required, but id is not?
string id = 3;
}
......
......@@ -71,9 +71,14 @@ func (r RoleServer) CreateRoles(ctx context.Context, request *apb.CreateRolesReq
}
for _, rrole := range request.Roles {
role := rbac.NewRole(uuid.New(), rrole.Name, rrole.Description, rrole.Permissions)
roleID, err := uuid.Parse(rrole.Id)
if err != nil {
roleID = uuid.New()
}
role := rbac.NewRole(roleID, rrole.Name, rrole.Description, rrole.Permissions)
err := r.roleService.Add(role)
err = r.roleService.Add(role)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
......
......@@ -92,7 +92,12 @@ func (u UserServer) CreateUsers(ctx context.Context, request *apb.CreateUsersReq
hashedPassword := base64.RawStdEncoding.EncodeToString(argon2.IDKey([]byte(user.Password), []byte(salt), 1, 64*1024, 4, 32))
user := rbac.NewUser(uuid.New(), user.Name, roles, string(hashedPassword), user.Token, salt, conflict.Metadata{ResourceVersion: 0})
userID, err := uuid.Parse(user.Id)
if err != nil {
userID = uuid.New()
}
user := rbac.NewUser(userID, user.Name, roles, string(hashedPassword), user.Token, salt, conflict.Metadata{ResourceVersion: 0})
err = u.userService.Add(user)
if err != nil {
log.Error(err)
......
......@@ -8,6 +8,9 @@ import (
configMgmtPb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/configurationmanagement"
ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/rbac"
"github.com/sirupsen/logrus"
"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/rbac"
"code.fbi.h-da.de/danet/gosdn/controller/api"
......@@ -16,7 +19,9 @@ import (
"google.golang.org/grpc/metadata"
)
func createContextWithAuthorization(loginResponse *rbac.LoginResponse) context.Context {
const admin = "admin"
func CreateContextWithAuthorization(loginResponse *rbac.LoginResponse) context.Context {
md := metadata.Pairs("authorize", loginResponse.Token)
return metadata.NewOutgoingContext(context.Background(), md)
}
......@@ -35,7 +40,7 @@ func CreateSecureConnection() (*grpc.ClientConn, context.Context, error) {
return nil, nil, err
}
sessionContext := createContextWithAuthorization(loginResp)
sessionContext := CreateContextWithAuthorization(loginResp)
dialOption := grpc.WithTransportCredentials(insecure.NewCredentials())
conn, err := grpc.Dial(controllerUrl, dialOption, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(100*1024*1024)))
......@@ -66,7 +71,7 @@ func CreateConnection() (*grpc.ClientConn, context.Context, error) {
// ExportCurrentSDNConfig can be used to save the current SDN config as a string to use in an other test later on.
func ExportCurrentSDNConfig(conn *grpc.ClientConn, ctx context.Context) (string, error) {
pndService := ppb.NewPndServiceClient(conn)
pndRes, err := pndService.GetPndList(ctx, &ppb.GetPndListRequest{Timestamp: getTimestamp()})
pndRes, err := pndService.GetPndList(ctx, &ppb.GetPndListRequest{Timestamp: GetTimestamp()})
if err != nil {
return "", err
}
......@@ -74,7 +79,7 @@ func ExportCurrentSDNConfig(conn *grpc.ClientConn, ctx context.Context) (string,
configMgmtService := configMgmtPb.NewConfigurationManagementServiceClient(conn)
sdnConfigResponse, err := configMgmtService.ExportSDNConfig(ctx, &configMgmtPb.ExportSDNConfigRequest{Timestamp: getTimestamp(), Pid: pndID})
sdnConfigResponse, err := configMgmtService.ExportSDNConfig(ctx, &configMgmtPb.ExportSDNConfigRequest{Timestamp: GetTimestamp(), Pid: pndID})
if err != nil {
return "", err
}
......@@ -85,7 +90,7 @@ func ExportCurrentSDNConfig(conn *grpc.ClientConn, ctx context.Context) (string,
// ApplySDNConfig can be used to apply a given SDN config as a string to set the testing environment as desired.
func ApplySDNConfig(conn *grpc.ClientConn, ctx context.Context, sdnConfig string) {
pndService := ppb.NewPndServiceClient(conn)
pndRes, err := pndService.GetPndList(ctx, &ppb.GetPndListRequest{Timestamp: getTimestamp()})
pndRes, err := pndService.GetPndList(ctx, &ppb.GetPndListRequest{Timestamp: GetTimestamp()})
if err != nil {
fmt.Println(err)
}
......@@ -95,12 +100,95 @@ func ApplySDNConfig(conn *grpc.ClientConn, ctx context.Context, sdnConfig string
configMgmtService := configMgmtPb.NewConfigurationManagementServiceClient(conn)
_, err = configMgmtService.ImportSDNConfig(ctx, &configMgmtPb.ImportSDNConfigRequest{Timestamp: getTimestamp(), Pid: pndID, SdnConfigData: sdnConfig})
_, err = configMgmtService.ImportSDNConfig(ctx, &configMgmtPb.ImportSDNConfigRequest{Timestamp: GetTimestamp(), Pid: pndID, SdnConfigData: sdnConfig})
if err != nil {
fmt.Println(err)
}
}
func getTimestamp() int64 {
func GetTimestamp() int64 {
return int64(time.Now().Nanosecond())
}
func CleanUserAndRolesExceptAdmin(conn *grpc.ClientConn, ctx context.Context) {
userService := apb.NewUserServiceClient(conn)
roleService := apb.NewRoleServiceClient(conn)
getAllUserResponse, err := userService.GetUsers(ctx, &apb.GetUsersRequest{
Timestamp: GetTimestamp(),
})
if err != nil {
logrus.Errorf("Error while cleaning up DB, %v", err)
}
err = cleanUsersExceptAdmin(getAllUserResponse, userService, ctx)
if err != nil {
logrus.Errorf("Error while cleaning up DB, %v", err)
}
getAllRoleResponse, err := roleService.GetRoles(ctx, &apb.GetRolesRequest{
Timestamp: GetTimestamp(),
})
if err != nil {
logrus.Errorf("Error while cleaning up DB, %v", err)
}
err = cleanRolesExceptAdmin(getAllRoleResponse, roleService, ctx)
if err != nil {
logrus.Errorf("Error while cleaning up DB, %v", err)
}
}
func cleanUsersExceptAdmin(resp *apb.GetUsersResponse, userService apb.UserServiceClient, ctx context.Context) error {
// no need to delete if only admin available
if len(resp.User) == 1 {
return nil
}
var names []string
for _, u := range resp.User {
if u.Name == admin {
continue
}
names = append(names, u.Name)
}
_, err := userService.DeleteUsers(ctx, &apb.DeleteUsersRequest{
Timestamp: GetTimestamp(),
Username: names,
})
if err != nil {
return err
}
return nil
}
func cleanRolesExceptAdmin(resp *apb.GetRolesResponse, roleService apb.RoleServiceClient, ctx context.Context) error {
// no need to delete if only admin available
if len(resp.Roles) == 1 {
return nil
}
var names []string
for _, role := range resp.Roles {
if role.Name == admin {
continue
}
names = append(names, role.Name)
}
_, err := roleService.DeleteRoles(ctx, &apb.DeleteRolesRequest{
Timestamp: GetTimestamp(),
RoleName: names,
})
if err != nil {
return err
}
return nil
}
package integration_test_rbac
import (
"context"
"fmt"
"testing"
"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/conflict"
mnepb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement"
apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/rbac"
"github.com/stretchr/testify/assert"
integration_test_utils "code.fbi.h-da.de/danet/gosdn/integration-tests/integrationTestUtils"
"google.golang.org/grpc"
)
const userID = "23224223-aeb6-433b-a797-2d671d7424f0"
const user1NameAndPW = "testUser1"
const pndID = "5f20f34b-cbd0-4511-9ddc-c50cf6a3b49d"
const roleID = "679f7982-d740-452e-b78d-c1d133233694"
// The connection to the controller to use in each test.
var conn *grpc.ClientConn
// The context containing the credentials when authenticated.
var ctx context.Context
// A defaultSDN config with default/empty values.
var defaultSDNConfig string
func TestMain(m *testing.M) {
localConn, localCtx, err := integration_test_utils.CreateSecureConnection()
if err != nil {
fmt.Println(err.Error())
}
conn = localConn
ctx = localCtx
sndConfig, err := integration_test_utils.ExportCurrentSDNConfig(conn, ctx)
defaultSDNConfig = sndConfig
if err != nil {
fmt.Println(err.Error())
}
integration_test_utils.CleanUserAndRolesExceptAdmin(conn, ctx)
m.Run()
}
func TestUserCreationAndModification(t *testing.T) {
defer integration_test_utils.CleanUserAndRolesExceptAdmin(conn, ctx)
// setup required parameters
const user2UUID = "0a28e837-473b-475d-b935-2457eb9462ae"
const expectedAmountOfUsers = 3
const expectedNameAfterChange = "testUser1Changed"
createUserRequest := &apb.CreateUsersRequest{
Timestamp: integration_test_utils.GetTimestamp(),
User: []*apb.User{
{
Id: userID,
Name: user1NameAndPW,
Roles: map[string]string{pndID: "admin", userID: "random"},
Password: user1NameAndPW,
Metadata: &conflict.Metadata{
ResourceVersion: 0,
},
},
{
Id: user2UUID,
Name: "user2",
Roles: map[string]string{pndID: "random"},
Password: user1NameAndPW,
Metadata: &conflict.Metadata{
ResourceVersion: 0,
},
},
},
}
getAllRequest := &apb.GetUsersRequest{
Timestamp: integration_test_utils.GetTimestamp(),
}
updateUserRequest := &apb.UpdateUsersRequest{
Timestamp: integration_test_utils.GetTimestamp(),
User: []*apb.UpdateUser{
{
Id: userID,
Name: expectedNameAfterChange,
Roles: map[string]string{},
Metadata: &conflict.Metadata{},
},
},
}
getUserRequest := &apb.GetUserRequest{
Timestamp: integration_test_utils.GetTimestamp(),
Id: userID,
Name: expectedNameAfterChange,
}
// setup gRPC services
userService := apb.NewUserServiceClient(conn)
// create two users
_, err := userService.CreateUsers(ctx, createUserRequest)
if err != nil {
t.Error(err)
t.FailNow()
}
// get all users and compare
getAllResponse, err := userService.GetUsers(ctx, getAllRequest)
if err != nil {
t.Error(err)
t.FailNow()
}
assert.Equal(t, expectedAmountOfUsers, len(getAllResponse.User))
assert.NotEqual(t, getAllResponse.User[1].Name, getAllResponse.User[2].Name)
assert.NotEqual(t, getAllResponse.User[1].Roles[pndID], getAllResponse.User[2].Roles[pndID])
// change name of user1
updateUserRequest.User[0].Roles = getAllResponse.User[1].Roles
updateUserRequest.User[0].Metadata.ResourceVersion = getAllResponse.User[1].Metadata.ResourceVersion
_, err = userService.UpdateUsers(ctx, updateUserRequest)
if err != nil {
t.Error(err)
t.FailNow()
}
getUserResponse, err := userService.GetUser(ctx, getUserRequest)
if err != nil {
t.Error(err)
t.FailNow()
}
assert.Equal(t, expectedNameAfterChange, getUserResponse.User.Name)
}
func TestRoleCreationAndModification(t *testing.T) {
defer integration_test_utils.CleanUserAndRolesExceptAdmin(conn, ctx)
// setup required parameters
const multiplePermissionRole = "multiple permission role"
const roleDescription = "A role with multiple permissions."
const multiplePermissionRoleNameAfterChange = "only two permission role"
const permissionToBeDeleted = "permission to be deleted"
const expectedAmountOfRoles = 3
const expectedAmountOfRolesAfterDeletion = 2
const expectedAmountOfPermissions = 3
const expectedAmountOfPermissionsAfterDeletion = 2
createRolesRequest := &apb.CreateRolesRequest{
Timestamp: integration_test_utils.GetTimestamp(),
Roles: []*apb.Role{
{
Id: roleID,
Name: multiplePermissionRole,
Description: roleDescription,
Permissions: []string{
"permission1",
"permission2",
permissionToBeDeleted,
},
},
{
Name: "random",
Description: "A random role with one permissions.",
Permissions: []string{
"permission1",
},
},
},
}
getAllRoleRequest := &apb.GetRolesRequest{
Timestamp: integration_test_utils.GetTimestamp(),
}
deleteRoleRequest := &apb.DeleteRolesRequest{
Timestamp: integration_test_utils.GetTimestamp(),
RoleName: []string{"random"},
}
removePermissionRequest := &apb.DeletePermissionsForRoleRequest{
Timestamp: integration_test_utils.GetTimestamp(),
RoleName: multiplePermissionRole,
PermissionsToDelete: []string{
permissionToBeDeleted,
},
}
updateRoleRequest := &apb.UpdateRolesRequest{
Timestamp: integration_test_utils.GetTimestamp(),
Roles: []*apb.Role{
{
Id: roleID,
Name: multiplePermissionRoleNameAfterChange,
Description: roleDescription,
},
},
}
getRoleRequest := &apb.GetRoleRequest{
Timestamp: integration_test_utils.GetTimestamp(),
Id: roleID,
RoleName: multiplePermissionRoleNameAfterChange,
}
// setup gRPC services
roleService := apb.NewRoleServiceClient(conn)
// create new roles
_, err := roleService.CreateRoles(ctx, createRolesRequest)
if err != nil {
t.Error(err)
t.FailNow()
}
// get roles and check amount
getAllRoleResponse, err := roleService.GetRoles(ctx, getAllRoleRequest)
if err != nil {
t.Error(err)
t.FailNow()
}
assert.Equal(t, expectedAmountOfRoles, len(getAllRoleResponse.Roles))
assert.Equal(t, multiplePermissionRole, getAllRoleResponse.Roles[1].Name)
assert.Equal(t, expectedAmountOfPermissions, len(getAllRoleResponse.Roles[1].Permissions))
// delete role and compare amount
_, err = roleService.DeleteRoles(ctx, deleteRoleRequest)
if err != nil {
t.Error(err)
t.FailNow()
}
getAllRoleResponse, err = roleService.GetRoles(ctx, getAllRoleRequest)
if err != nil {
t.Error(err)
t.FailNow()
}
assert.Equal(t, expectedAmountOfRolesAfterDeletion, len(getAllRoleResponse.Roles))
// delete one permission then get role to compare
_, err = roleService.DeletePermissionsForRole(ctx, removePermissionRequest)
if err != nil {
t.Error(err)
t.FailNow()
}
getAllRoleResponse, err = roleService.GetRoles(ctx, getAllRoleRequest)
if err != nil {
t.Error(err)
t.FailNow()
}
assert.Equal(t, expectedAmountOfPermissionsAfterDeletion, len(getAllRoleResponse.Roles[1].Permissions))
// change role name and compare
_, err = roleService.UpdateRoles(ctx, updateRoleRequest)
if err != nil {
t.Error(err)
t.FailNow()
}
getRoleResponse, err := roleService.GetRole(ctx, getRoleRequest)
if err != nil {
t.Error(err)
t.FailNow()
}
assert.Equal(t, multiplePermissionRoleNameAfterChange, getRoleResponse.Role.Name)
}
func TestUserWithoutPermission(t *testing.T) {
defer integration_test_utils.CleanUserAndRolesExceptAdmin(conn, ctx)
// setup required parameters
const roleName = "peter"
createUserRequestPreparation := &apb.CreateUsersRequest{
Timestamp: integration_test_utils.GetTimestamp(),
User: []*apb.User{
{
Id: userID,
Name: user1NameAndPW,
Roles: map[string]string{pndID: roleName},
Password: user1NameAndPW,
Metadata: &conflict.Metadata{
ResourceVersion: 0,
},
},
},
}
createUserRequestTestCase := &apb.CreateUsersRequest{
Timestamp: integration_test_utils.GetTimestamp(),
User: []*apb.User{
{
Id: "b22c4e46-fa54-4226-8e61-134c895bef5b",
Name: "test",
Roles: map[string]string{pndID: "admin"},
Password: user1NameAndPW,
Metadata: &conflict.Metadata{
ResourceVersion: 0,
},
},
},
}
createRoleRequest := &apb.CreateRolesRequest{
Timestamp: integration_test_utils.GetTimestamp(),
Roles: []*apb.Role{
{
Name: roleName,
Description: "Something that only a peter can do.",
Permissions: []string{
"/gosdn.rbac.UserService/CreateUsers",
"/gosdn.networkelement.NetworkElementService/GetAllFlattened",
},
},
},
}
loginRequest := &apb.LoginRequest{
Timestamp: integration_test_utils.GetTimestamp(),
Username: user1NameAndPW,
Pwd: user1NameAndPW,
}
// setup gRPC services
userService := apb.NewUserServiceClient(conn)
roleService := apb.NewRoleServiceClient(conn)
authService := apb.NewAuthServiceClient(conn)
mneService := mnepb.NewNetworkElementServiceClient(conn)
// create a user and its role
_, err := userService.CreateUsers(ctx, createUserRequestPreparation)
if err != nil {
t.Error(err)
t.FailNow()
}
_, err = roleService.CreateRoles(ctx, createRoleRequest)
if err != nil {
t.Error(err)
t.FailNow()
}
// login new user
loginResponse, err := authService.Login(context.Background(), loginRequest)
if err != nil {
t.Error(err)
t.FailNow()
}
sessionToken := integration_test_utils.CreateContextWithAuthorization(loginResponse)
// test if user can get all MNE, should fail
_, err = mneService.GetAll(sessionToken, &mnepb.GetAllRequest{
Timestamp: integration_test_utils.GetTimestamp(),
Pid: pndID,
},
)
assert.NotEqual(t, nil, err)
// test if user can get all flattened MNE, should work
_, err = mneService.GetAllFlattened(sessionToken, &mnepb.GetAllFlattenedRequest{
Timestamp: integration_test_utils.GetTimestamp(),
Pid: pndID,
},
)
assert.Equal(t, nil, err)
// test if user1 can create user with admin role, should fail
_, _ = userService.CreateUsers(sessionToken, createUserRequestTestCase)
//TODO(faseid): implement mechanism to stop random user from creating admin user,
// then uncomment test case
//assert.NotEqual(t, nil, err)
// test if user1 can create user with random role, should work
createUserRequestTestCase.User[0].Roles[pndID] = "peter 2"
_, err = userService.CreateUsers(sessionToken, createUserRequestTestCase)
assert.Equal(t, nil, err)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment