Skip to content
Snippets Groups Projects

Improve test coverage of rbac stuff

Merged Ghost User requested to merge 207-improve-test-coverage-of-rbac-stuff into develop
All threads resolved!
5 files
+ 787
1071
Compare changes
  • Side-by-side
  • Inline
Files
5
@@ -8,9 +8,7 @@ import (
"code.fbi.h-da.de/danet/gosdn/controller/metrics"
"code.fbi.h-da.de/danet/gosdn/controller/rbac"
"code.fbi.h-da.de/danet/gosdn/controller/store"
"github.com/google/uuid"
"github.com/prometheus/client_golang/prometheus"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -87,145 +85,6 @@ func (s Auth) Logout(ctx context.Context, request *apb.LogoutRequest) (*apb.Logo
}, nil
}
// CreateUsers creates new users, can be 1 or more
func (s Auth) CreateUsers(ctx context.Context, request *apb.CreateUsersRequest) (*apb.CreateUsersResponse, error) {
labels := prometheus.Labels{"service": "auth", "rpc": "post"}
start := metrics.StartHook(labels, grpcRequestsTotal)
defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
// TODO: implement check if user is allowed to create users with this role
// e.g. non-admin shouldn't be allowed to create admin users
for _, u := range request.User {
roles := map[string]string{}
for key, elem := range u.Roles {
_, err := uuid.Parse(key)
if err != nil {
return nil, handleRPCError(labels, err)
}
roles[key] = elem
}
user := rbac.NewUser(uuid.New(), u.Name, roles, u.Password, u.Token)
err := userc.Add(user)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
}
return &apb.CreateUsersResponse{
Timestamp: time.Now().UnixNano(),
Status: apb.Status_STATUS_OK,
}, nil
}
// GetUser returns one user by name.
func (s Auth) GetUser(ctx context.Context, request *apb.GetUserRequest) (*apb.GetUserResponse, error) {
labels := prometheus.Labels{"service": "auth", "rpc": "get"}
start := metrics.StartHook(labels, grpcRequestsTotal)
defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
// TODO: implement check if user is allowed to get this user data; only their own if not admin
userData, err := userc.Get(store.Query{Name: request.Name})
if err != nil {
return nil, err
}
user := &apb.User{
Id: userData.ID().String(),
Name: userData.Name(),
Roles: userData.GetRoles(),
}
return &apb.GetUserResponse{
Timestamp: time.Now().UnixNano(),
Status: apb.Status_STATUS_OK,
User: user,
}, nil
}
// GetUsers returns all availbale users
func (s Auth) GetUsers(ctx context.Context, request *apb.GetUsersRequest) (*apb.GetUsersResponse, error) {
labels := prometheus.Labels{"service": "auth", "rpc": "get"}
start := metrics.StartHook(labels, grpcRequestsTotal)
defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
userList, err := userc.GetAll()
if err != nil {
return nil, err
}
users := []*apb.User{}
for _, u := range userList {
users = append(users, &apb.User{
Id: u.ID().String(),
Name: u.Name(),
Roles: u.GetRoles(),
})
}
return &apb.GetUsersResponse{
Timestamp: time.Now().UnixNano(),
Status: apb.Status_STATUS_OK,
User: users,
}, nil
}
// UpdateUsers updates the user data of one or more users provided in the request
func (s Auth) UpdateUsers(ctx context.Context, request *apb.UpdateUsersRequest) (*apb.UpdateUsersResponse, error) {
labels := prometheus.Labels{"service": "auth", "rpc": "post"}
start := metrics.StartHook(labels, grpcRequestsTotal)
defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
// TODO: check if current user is allowed to update the user they try to update; only their own if not admin
for _, u := range request.User {
uid, err := uuid.Parse(u.Id)
if err != nil {
return nil, handleRPCError(labels, err)
}
_, err = userc.Get(store.Query{ID: uid})
if err != nil {
return nil, status.Errorf(codes.Canceled, "user not found %v", err)
}
userToUpdate := rbac.NewUser(uid, u.Name, u.Roles, u.Password, u.Token)
err = userc.Update(userToUpdate)
if err != nil {
return nil, status.Errorf(codes.Aborted, "could not update user %v", err)
}
}
return &apb.UpdateUsersResponse{
Timestamp: time.Now().UnixNano(),
Status: apb.Status_STATUS_OK,
}, nil
}
// DeleteUsers deletes one or more users provided in the request
func (s Auth) DeleteUsers(ctx context.Context, request *apb.DeleteUsersRequest) (*apb.DeleteUsersResponse, error) {
labels := prometheus.Labels{"service": "auth", "rpc": "delete"}
start := metrics.StartHook(labels, grpcRequestsTotal)
defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
for _, u := range request.Username {
userToDelete, err := userc.Get(store.Query{Name: u})
if err != nil {
return nil, status.Errorf(codes.Canceled, "user not found %v", err)
}
err = userc.Delete(userToDelete)
if err != nil {
return nil, status.Errorf(codes.Aborted, "error deleting user %v", err)
}
}
return &apb.DeleteUsersResponse{
Timestamp: time.Now().UnixNano(),
Status: apb.Status_STATUS_OK,
}, nil
}
func (s Auth) isValidUser(user rbac.User) (bool, error) {
storedUser, err := userc.Get(store.Query{Name: user.Name()})
if err != nil {
@@ -242,175 +101,3 @@ func (s Auth) isValidUser(user rbac.User) (bool, error) {
return false, status.Errorf(codes.Unauthenticated, "incorrect user name or password")
}
// CreateRoles creates roles with permissions for the roles used in rbac.
func (s Auth) CreateRoles(ctx context.Context, request *apb.CreateRolesRequest) (*apb.CreateRolesResponse, error) {
labels := prometheus.Labels{"service": "auth", "rpc": "post"}
start := metrics.StartHook(labels, grpcRequestsTotal)
defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
for _, r := range request.Roles {
role := rbac.NewRole(uuid.New(), r.Name, r.Description, r.Permissions)
err := rolec.Add(role)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
}
return &apb.CreateRolesResponse{
Timestamp: time.Now().UnixNano(),
Status: apb.Status_STATUS_OK,
}, nil
}
// GetRole returns one role with its permissions found by name.
func (s Auth) GetRole(ctx context.Context, request *apb.GetRoleRequest) (*apb.GetRoleResponse, error) {
labels := prometheus.Labels{"service": "auth", "rpc": "get"}
start := metrics.StartHook(labels, grpcRequestsTotal)
defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
roleData, err := rolec.Get(store.Query{Name: request.RoleName})
if err != nil {
return nil, err
}
role := &apb.Role{
Id: roleData.ID().String(),
Name: roleData.Name(),
Description: roleData.GetDescription(),
Permissions: roleData.GetPermissions(),
}
return &apb.GetRoleResponse{
Timestamp: time.Now().UnixNano(),
Status: apb.Status_STATUS_OK,
Role: role,
}, nil
}
// GetRoles returns all roles with their permissions.
func (s Auth) GetRoles(ctx context.Context, request *apb.GetRolesRequest) (*apb.GetRolesResponse, error) {
labels := prometheus.Labels{"service": "auth", "rpc": "get"}
start := metrics.StartHook(labels, grpcRequestsTotal)
defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
roleList, err := rolec.GetAll()
if err != nil {
return nil, err
}
roles := []*apb.Role{}
for _, r := range roleList {
roles = append(roles, &apb.Role{
Id: r.ID().String(),
Name: r.Name(),
Description: r.GetDescription(),
Permissions: r.GetPermissions(),
})
}
return &apb.GetRolesResponse{
Timestamp: time.Now().UnixNano(),
Status: apb.Status_STATUS_OK,
Roles: roles,
}, nil
}
// UpdateRoles updates data of the provided roles.
func (s Auth) UpdateRoles(ctx context.Context, request *apb.UpdateRolesRequest) (*apb.UpdateRolesResponse, error) {
labels := prometheus.Labels{"service": "auth", "rpc": "post"}
start := metrics.StartHook(labels, grpcRequestsTotal)
defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
// TODO: check if current user is allowed to update the role they try to update; only their own if not admin
for _, r := range request.Roles {
rid, err := uuid.Parse(r.Id)
if err != nil {
return nil, handleRPCError(labels, err)
}
_, err = rolec.Get(store.Query{ID: rid})
if err != nil {
return nil, status.Errorf(codes.Canceled, "role not found %v", err)
}
roleToUpdate := rbac.NewRole(rid, r.Name, r.Description, r.Permissions)
err = rolec.Update(roleToUpdate)
if err != nil {
return nil, status.Errorf(codes.Aborted, "could not update role %v", err)
}
}
return &apb.UpdateRolesResponse{
Timestamp: time.Now().UnixNano(),
Status: apb.Status_STATUS_OK,
}, nil
}
// DeletePermissionsForRole deletes the provided permissions from one role found by name.
func (s Auth) DeletePermissionsForRole(ctx context.Context, request *apb.DeletePermissionsForRoleRequest) (*apb.DeletePermissionsForRoleResponse, error) {
labels := prometheus.Labels{"service": "auth", "rpc": "delete"}
start := metrics.StartHook(labels, grpcRequestsTotal)
defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
roleToUpdate, err := rolec.Get(store.Query{Name: request.RoleName})
if err != nil {
return nil, status.Errorf(codes.Canceled, "role not found %v", err)
}
// checks if there is at least one valid permission to delete
// in the provided set of permissions to delete
nonFound := true
for _, perm := range roleToUpdate.GetPermissions() {
for _, permToDelete := range request.PermissionsToDelete {
if perm == permToDelete {
nonFound = false
break
}
}
if !nonFound {
break
}
}
if nonFound {
return nil, status.Errorf(codes.Canceled, "no fitting permissions")
}
// updates the existing role with the trimmed set of permissions
roleToUpdate.RemovePermissionsFromRole(request.PermissionsToDelete)
err = rolec.Update(roleToUpdate)
if err != nil {
return nil, status.Errorf(codes.Aborted, "could not update role %v", err)
}
return &apb.DeletePermissionsForRoleResponse{
Timestamp: time.Now().UnixNano(),
Status: apb.Status_STATUS_OK,
}, nil
}
// DeleteRoles deletes all the provided roles with their permissions.
func (s Auth) DeleteRoles(ctx context.Context, request *apb.DeleteRolesRequest) (*apb.DeleteRolesResponse, error) {
labels := prometheus.Labels{"service": "auth", "rpc": "delete"}
start := metrics.StartHook(labels, grpcRequestsTotal)
defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
for _, r := range request.RoleName {
roleToDelete, err := rolec.Get(store.Query{Name: r})
if err != nil {
return nil, status.Errorf(codes.Canceled, "role not found")
}
err = rolec.Delete(roleToDelete)
if err != nil {
return nil, status.Errorf(codes.Aborted, "error deleting role %v", err)
}
}
return &apb.DeleteRolesResponse{
Timestamp: time.Now().UnixNano(),
Status: apb.Status_STATUS_OK,
}, nil
}
Loading