2020-06-22 06:56:27 -07:00
// Copyright (c) HashiCorp, Inc.
2023-02-02 17:15:17 -08:00
// SPDX-License-Identifier: BUSL-1.1
2020-06-22 06:56:27 -07:00
package roles_test
import (
"context"
2020-09-23 08:10:27 -07:00
"errors"
2020-06-22 06:56:27 -07:00
"fmt"
2023-12-15 11:49:59 -08:00
"slices"
2024-02-13 10:50:06 -05:00
"sort"
2020-06-22 06:56:27 -07:00
"strings"
"testing"
2020-07-17 09:31:10 -07:00
"github.com/google/go-cmp/cmp"
2023-10-31 13:44:17 +00:00
"github.com/google/go-cmp/cmp/cmpopts"
2022-10-28 15:52:06 -04:00
"github.com/hashicorp/boundary/globals"
2023-06-26 17:05:54 -04:00
"github.com/hashicorp/boundary/internal/auth/ldap"
2021-06-04 09:44:57 -05:00
"github.com/hashicorp/boundary/internal/auth/oidc"
2023-12-15 11:49:59 -08:00
"github.com/hashicorp/boundary/internal/auth/password"
"github.com/hashicorp/boundary/internal/authtoken"
2022-05-09 12:45:10 -07:00
"github.com/hashicorp/boundary/internal/daemon/controller/auth"
"github.com/hashicorp/boundary/internal/daemon/controller/handlers"
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/roles"
2020-08-10 17:15:02 -04:00
"github.com/hashicorp/boundary/internal/db"
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
2023-12-15 11:49:59 -08:00
authpb "github.com/hashicorp/boundary/internal/gen/controller/auth"
2020-08-10 17:15:02 -04:00
"github.com/hashicorp/boundary/internal/iam"
2021-06-04 09:44:57 -05:00
"github.com/hashicorp/boundary/internal/kms"
2020-08-10 17:15:02 -04:00
"github.com/hashicorp/boundary/internal/perms"
2023-12-15 11:49:59 -08:00
"github.com/hashicorp/boundary/internal/requests"
"github.com/hashicorp/boundary/internal/server"
2020-08-10 17:15:02 -04:00
"github.com/hashicorp/boundary/internal/types/scope"
2021-08-26 10:44:41 -04:00
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/roles"
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes"
2023-06-06 16:13:44 -04:00
"github.com/hashicorp/boundary/version"
2021-06-04 09:44:57 -05:00
"github.com/kr/pretty"
2020-06-22 06:56:27 -07:00
"google.golang.org/genproto/protobuf/field_mask"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
2020-07-17 09:31:10 -07:00
"google.golang.org/protobuf/testing/protocmp"
2021-04-23 09:13:37 -05:00
"google.golang.org/protobuf/types/known/timestamppb"
2020-06-22 06:56:27 -07:00
"google.golang.org/protobuf/types/known/wrapperspb"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
2024-01-23 14:33:09 -05:00
var testAuthorizedActions = [] string { "no-op" , "read" , "update" , "delete" , "add-principals" , "set-principals" , "remove-principals" , "add-grants" , "set-grants" , "remove-grants" , "add-grant-scopes" , "set-grant-scopes" , "remove-grant-scopes" }
2021-04-23 09:13:37 -05:00
2020-06-29 11:12:40 -07:00
func createDefaultRolesAndRepo ( t * testing . T ) ( * iam . Role , * iam . Role , func () ( * iam . Repository , error )) {
2020-06-22 06:56:27 -07:00
t . Helper ()
2020-07-06 10:15:01 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
2020-06-22 06:56:27 -07:00
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-06-22 06:56:27 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-06-22 06:56:27 -07:00
}
2020-08-19 16:47:18 -04:00
o , p := iam . TestScopes ( t , iamRepo )
2024-06-17 12:09:33 -07:00
or := iam . TestRole ( t , conn , o . GetPublicId (), iam . WithDescription ( "default" ), iam . WithName ( "default" ), iam . WithGrantScopeIds ([] string { p . GetPublicId ()}))
2020-06-29 11:12:40 -07:00
pr := iam . TestRole ( t , conn , p . GetPublicId (), iam . WithDescription ( "default" ), iam . WithName ( "default" ))
return or , pr , repoFn
2020-06-22 06:56:27 -07:00
}
2020-07-14 14:32:47 -07:00
func equalPrincipals ( role * pb . Role , principals [] string ) bool {
if len ( role . Principals ) != len ( principals ) {
return false
}
for _ , principal := range principals {
var foundInPrincipals bool
var foundInPrincipalIds bool
for _ , v := range role . Principals {
if v . Id == principal {
foundInPrincipals = true
}
}
for _ , v := range role . PrincipalIds {
if v == principal {
foundInPrincipalIds = true
}
}
if ! foundInPrincipals || ! foundInPrincipalIds {
return false
}
}
return true
}
2020-06-22 06:56:27 -07:00
func TestGet ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2021-03-25 03:15:43 -04:00
or , pr , repoFn := createDefaultRolesAndRepo ( t )
2020-06-22 06:56:27 -07:00
toMerge := & pbs . GetRoleRequest {
2020-07-22 00:14:28 -04:00
Id : or . GetPublicId (),
2020-06-22 06:56:27 -07:00
}
2020-06-29 11:12:40 -07:00
wantOrgRole := & pb . Role {
2021-01-20 10:53:01 -05:00
Id : or . GetPublicId (),
ScopeId : or . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : or . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2021-01-20 10:53:01 -05:00
Name : & wrapperspb . StringValue { Value : or . GetName ()},
Description : & wrapperspb . StringValue { Value : or . GetDescription ()},
2024-01-23 14:33:09 -05:00
GrantScopeIds : [] string { pr . GetScopeId ()},
2021-01-20 10:53:01 -05:00
CreatedTime : or . CreateTime . GetTimestamp (),
UpdatedTime : or . UpdateTime . GetTimestamp (),
Version : or . GetVersion (),
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-29 11:12:40 -07:00
}
wantProjRole := & pb . Role {
2021-01-20 10:53:01 -05:00
Id : pr . GetPublicId (),
ScopeId : pr . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : pr . GetScopeId (), Type : scope . Project . String (), ParentScopeId : or . GetScopeId ()},
2021-01-20 10:53:01 -05:00
Name : & wrapperspb . StringValue { Value : pr . GetName ()},
Description : & wrapperspb . StringValue { Value : pr . GetDescription ()},
2024-01-23 14:33:09 -05:00
GrantScopeIds : [] string { globals . GrantScopeThis },
2021-01-20 10:53:01 -05:00
CreatedTime : pr . CreateTime . GetTimestamp (),
UpdatedTime : pr . UpdateTime . GetTimestamp (),
Version : pr . GetVersion (),
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-22 06:56:27 -07:00
}
cases := [] struct {
name string
2020-07-22 00:14:28 -04:00
scopeId string
2020-06-22 06:56:27 -07:00
req * pbs . GetRoleRequest
res * pbs . GetRoleResponse
2020-09-23 08:10:27 -07:00
err error
2020-06-22 06:56:27 -07:00
}{
{
name : "Get an Existing Role" ,
2020-07-22 00:14:28 -04:00
scopeId : or . GetScopeId (),
2020-06-29 11:12:40 -07:00
req : & pbs . GetRoleRequest { Id : or . GetPublicId ()},
res : & pbs . GetRoleResponse { Item : wantOrgRole },
2020-06-22 06:56:27 -07:00
},
{
2024-02-16 08:30:16 -05:00
name : "Get a non existent Role" ,
2023-03-10 15:06:39 -05:00
req : & pbs . GetRoleRequest { Id : globals . RolePrefix + "_DoesntExis" },
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . NotFound ),
2020-06-22 06:56:27 -07:00
},
{
2020-09-23 08:10:27 -07:00
name : "Wrong id prefix" ,
req : & pbs . GetRoleRequest { Id : "j_1234567890" },
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-22 06:56:27 -07:00
},
{
2020-09-23 08:10:27 -07:00
name : "space in id" ,
2023-03-10 15:06:39 -05:00
req : & pbs . GetRoleRequest { Id : globals . RolePrefix + "_1 23456789" },
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-22 06:56:27 -07:00
},
2020-06-29 11:12:40 -07:00
{
name : "Project Scoped Get an Existing Role" ,
2020-07-22 00:14:28 -04:00
scopeId : pr . GetScopeId (),
req : & pbs . GetRoleRequest { Id : pr . GetPublicId ()},
2020-06-29 11:12:40 -07:00
res : & pbs . GetRoleResponse { Item : wantProjRole },
},
{
2024-02-16 08:30:16 -05:00
name : "Project Scoped Get a non existent Role" ,
2020-07-22 00:14:28 -04:00
scopeId : pr . GetScopeId (),
2023-03-10 15:06:39 -05:00
req : & pbs . GetRoleRequest { Id : globals . RolePrefix + "_DoesntExis" },
2020-06-29 11:12:40 -07:00
res : nil ,
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . NotFound ),
2020-06-29 11:12:40 -07:00
},
{
name : "Project Scoped Wrong id prefix" ,
2020-07-22 00:14:28 -04:00
scopeId : pr . GetScopeId (),
req : & pbs . GetRoleRequest { Id : "j_1234567890" },
2020-06-29 11:12:40 -07:00
res : nil ,
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-29 11:12:40 -07:00
},
{
name : "Project Scoped space in id" ,
2020-07-22 00:14:28 -04:00
scopeId : pr . GetScopeId (),
2023-03-10 15:06:39 -05:00
req : & pbs . GetRoleRequest { Id : globals . RolePrefix + "_1 23456789" },
2020-06-29 11:12:40 -07:00
res : nil ,
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-29 11:12:40 -07:00
},
2020-06-22 06:56:27 -07:00
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
req := proto . Clone ( toMerge ).( * pbs . GetRoleRequest )
proto . Merge ( req , tc . req )
2023-12-15 11:49:59 -08:00
s , err := roles . NewService ( context . Background (), repoFn , 1000 )
2020-06-22 06:56:27 -07:00
require . NoError ( err , "Couldn't create new role service." )
2021-03-25 03:15:43 -04:00
got , gErr := s . GetRole ( auth . DisabledAuthTestContext ( repoFn , tc . scopeId ), req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "GetRole(%+v) got error %v, wanted %v" , req , gErr , tc . err )
}
2023-10-31 13:44:17 +00:00
assert . Empty ( cmp . Diff (
got ,
tc . res ,
protocmp . Transform (),
cmpopts . SortSlices ( func ( a , b string ) bool {
return a < b
}),
), "GetRole(%q) got response\n%q, wanted\n%q" , req , got , tc . res )
2020-06-22 06:56:27 -07:00
})
}
}
func TestList ( t * testing . T ) {
2023-12-15 11:49:59 -08:00
ctx := context . Background ()
2020-07-06 10:15:01 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
2020-06-22 06:56:27 -07:00
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-06-22 06:56:27 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-06-22 06:56:27 -07:00
}
2020-09-29 20:38:16 -04:00
oNoRoles , pWithRoles := iam . TestScopes ( t , iamRepo , iam . WithSkipDefaultRoleCreation ( true ))
oWithRoles , pNoRoles := iam . TestScopes ( t , iamRepo , iam . WithSkipDefaultRoleCreation ( true ))
2020-06-29 11:12:40 -07:00
var wantOrgRoles [] * pb . Role
var wantProjRoles [] * pb . Role
2021-01-23 13:39:04 -05:00
var totalRoles [] * pb . Role
2020-06-22 06:56:27 -07:00
for i := 0 ; i < 10 ; i ++ {
2020-06-29 11:12:40 -07:00
or := iam . TestRole ( t , conn , oWithRoles . GetPublicId ())
2024-06-25 13:05:52 -04:00
_ = iam . TestRoleGrantScope ( t , conn , or . GetPublicId (), globals . GrantScopeChildren )
2020-06-29 11:12:40 -07:00
wantOrgRoles = append ( wantOrgRoles , & pb . Role {
2021-01-20 10:53:01 -05:00
Id : or . GetPublicId (),
ScopeId : or . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : or . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2021-01-20 10:53:01 -05:00
CreatedTime : or . GetCreateTime (). GetTimestamp (),
UpdatedTime : or . GetUpdateTime (). GetTimestamp (),
Version : or . GetVersion (),
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2024-06-25 13:05:52 -04:00
GrantScopeIds : [] string { "this" , "children" },
2020-06-29 11:12:40 -07:00
})
2021-01-23 13:39:04 -05:00
totalRoles = append ( totalRoles , wantOrgRoles [ i ])
2020-06-29 11:12:40 -07:00
pr := iam . TestRole ( t , conn , pWithRoles . GetPublicId ())
wantProjRoles = append ( wantProjRoles , & pb . Role {
2021-01-20 10:53:01 -05:00
Id : pr . GetPublicId (),
ScopeId : pr . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : pr . GetScopeId (), Type : scope . Project . String (), ParentScopeId : oNoRoles . GetPublicId ()},
2021-01-20 10:53:01 -05:00
CreatedTime : pr . GetCreateTime (). GetTimestamp (),
UpdatedTime : pr . GetUpdateTime (). GetTimestamp (),
Version : pr . GetVersion (),
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2024-06-25 13:05:52 -04:00
GrantScopeIds : [] string { "this" },
2020-06-22 06:56:27 -07:00
})
2021-01-23 13:39:04 -05:00
totalRoles = append ( totalRoles , wantProjRoles [ i ])
2020-06-22 06:56:27 -07:00
}
2023-12-15 11:49:59 -08:00
slices . Reverse ( wantOrgRoles )
slices . Reverse ( wantProjRoles )
slices . Reverse ( totalRoles )
// Run analyze to update postgres estimates
sqlDb , err := conn . SqlDB ( ctx )
require . NoError ( t , err )
_ , err = sqlDb . ExecContext ( ctx , "analyze" )
require . NoError ( t , err )
2020-06-22 06:56:27 -07:00
cases := [] struct {
2020-09-23 08:10:27 -07:00
name string
req * pbs . ListRolesRequest
res * pbs . ListRolesResponse
2021-02-22 10:09:25 -07:00
err error
2020-06-22 06:56:27 -07:00
}{
{
2020-09-23 08:10:27 -07:00
name : "List Many Role" ,
req : & pbs . ListRolesRequest { ScopeId : oWithRoles . GetPublicId ()},
2023-12-15 11:49:59 -08:00
res : & pbs . ListRolesResponse {
Items : wantOrgRoles ,
EstItemCount : uint32 ( len ( wantOrgRoles )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
2020-06-22 06:56:27 -07:00
},
{
2020-09-23 08:10:27 -07:00
name : "List No Roles" ,
req : & pbs . ListRolesRequest { ScopeId : oNoRoles . GetPublicId ()},
2023-12-15 11:49:59 -08:00
res : & pbs . ListRolesResponse {
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
},
{
name : "Paginate listing" ,
req : & pbs . ListRolesRequest { ScopeId : "global" , Recursive : true , PageSize : 2 },
res : & pbs . ListRolesResponse {
Items : totalRoles [: 2 ],
EstItemCount : uint32 ( len ( totalRoles )),
ResponseType : "delta" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
2020-06-22 06:56:27 -07:00
},
2020-06-29 11:12:40 -07:00
{
2020-09-23 08:10:27 -07:00
name : "List Many Project Role" ,
req : & pbs . ListRolesRequest { ScopeId : pWithRoles . GetPublicId ()},
2023-12-15 11:49:59 -08:00
res : & pbs . ListRolesResponse {
Items : wantProjRoles ,
EstItemCount : uint32 ( len ( wantProjRoles )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
2020-06-29 11:12:40 -07:00
},
{
2020-09-23 08:10:27 -07:00
name : "List No Project Roles" ,
req : & pbs . ListRolesRequest { ScopeId : pNoRoles . GetPublicId ()},
2023-12-15 11:49:59 -08:00
res : & pbs . ListRolesResponse {
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
2020-06-29 11:12:40 -07:00
},
2021-01-23 13:39:04 -05:00
{
2021-01-25 19:37:40 -05:00
name : "List proj roles recursively" ,
req : & pbs . ListRolesRequest { ScopeId : pWithRoles . GetPublicId (), Recursive : true },
res : & pbs . ListRolesResponse {
2023-12-15 11:49:59 -08:00
Items : wantProjRoles ,
EstItemCount : uint32 ( len ( wantProjRoles )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
2021-01-25 19:37:40 -05:00
},
},
{
name : "List org roles recursively" ,
2021-01-23 13:39:04 -05:00
req : & pbs . ListRolesRequest { ScopeId : oNoRoles . GetPublicId (), Recursive : true },
res : & pbs . ListRolesResponse {
2023-12-15 11:49:59 -08:00
Items : wantProjRoles ,
EstItemCount : uint32 ( len ( wantProjRoles )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
2021-01-23 13:39:04 -05:00
},
},
{
name : "List global roles recursively" ,
req : & pbs . ListRolesRequest { ScopeId : "global" , Recursive : true },
res : & pbs . ListRolesResponse {
2023-12-15 11:49:59 -08:00
Items : totalRoles ,
EstItemCount : uint32 ( len ( totalRoles )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
2021-01-23 13:39:04 -05:00
},
},
2021-02-22 10:09:25 -07:00
{
name : "Filter to org roles" ,
req : & pbs . ListRolesRequest { ScopeId : "global" , Recursive : true , Filter : fmt . Sprintf ( `"/item/scope/id"==%q` , oWithRoles . GetPublicId ())},
2023-12-15 11:49:59 -08:00
res : & pbs . ListRolesResponse {
Items : wantOrgRoles ,
EstItemCount : uint32 ( len ( wantOrgRoles )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
2021-02-22 10:09:25 -07:00
},
{
name : "Filter to proj roles" ,
req : & pbs . ListRolesRequest { ScopeId : "global" , Recursive : true , Filter : fmt . Sprintf ( `"/item/scope/id"==%q` , pWithRoles . GetPublicId ())},
2023-12-15 11:49:59 -08:00
res : & pbs . ListRolesResponse {
Items : wantProjRoles ,
EstItemCount : uint32 ( len ( wantProjRoles )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
2021-02-22 10:09:25 -07:00
},
{
name : "Filter to no roles" ,
req : & pbs . ListRolesRequest { ScopeId : pWithRoles . GetPublicId (), Filter : `"/item/id"=="doesnt match"` },
2023-12-15 11:49:59 -08:00
res : & pbs . ListRolesResponse {
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
2021-02-22 10:09:25 -07:00
},
{
name : "Filter Bad Format" ,
req : & pbs . ListRolesRequest { ScopeId : pWithRoles . GetPublicId (), Filter : `"//id/"=="bad"` },
err : handlers . InvalidArgumentErrorf ( "bad format" , nil ),
},
2020-06-22 06:56:27 -07:00
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
2021-01-23 13:39:04 -05:00
assert , require := assert . New ( t ), require . New ( t )
2023-12-15 11:49:59 -08:00
s , err := roles . NewService ( context . Background (), repoFn , 1000 )
2020-06-22 06:56:27 -07:00
require . NoError ( err , "Couldn't create new role service." )
2021-05-04 19:57:35 -05:00
// Test the non-anon case
2021-03-25 03:15:43 -04:00
got , gErr := s . ListRoles ( auth . DisabledAuthTestContext ( repoFn , tc . req . GetScopeId ()), tc . req )
2021-02-22 10:09:25 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ))
2021-05-04 19:57:35 -05:00
return
2021-02-22 10:09:25 -07:00
}
2021-05-04 19:57:35 -05:00
require . NoError ( gErr )
2023-10-31 13:44:17 +00:00
assert . Empty ( cmp . Diff (
got ,
tc . res ,
protocmp . Transform (),
2023-12-15 11:49:59 -08:00
protocmp . IgnoreFields ( & pbs . ListRolesResponse {}, "list_token" ),
2023-10-31 13:44:17 +00:00
cmpopts . SortSlices ( func ( a , b string ) bool {
return a < b
}),
), "ListRoles(%q) got response %q, wanted %q" , tc . req , got , tc . res )
2021-05-04 19:57:35 -05:00
// Test the anon case
2022-10-28 15:52:06 -04:00
got , gErr = s . ListRoles ( auth . DisabledAuthTestContext ( repoFn , tc . req . GetScopeId (), auth . WithUserId ( globals . AnonymousUserId )), tc . req )
2021-05-04 19:57:35 -05:00
require . NoError ( gErr )
assert . Len ( got . Items , len ( tc . res . Items ))
for _ , item := range got . GetItems () {
require . Nil ( item . CreatedTime )
require . Nil ( item . PrincipalIds )
require . Nil ( item . Principals )
require . Nil ( item . Grants )
require . Nil ( item . GrantStrings )
require . Nil ( item . UpdatedTime )
require . Zero ( item . Version )
}
2020-06-22 06:56:27 -07:00
})
}
}
2023-12-15 11:49:59 -08:00
func roleToProto ( r * iam . Role , scope * scopes . ScopeInfo , authorizedActions [] string ) * pb . Role {
2024-06-25 13:05:52 -04:00
ret := & pb . Role {
2023-12-15 11:49:59 -08:00
Id : r . GetPublicId (),
ScopeId : r . GetScopeId (),
Scope : scope ,
CreatedTime : r . GetCreateTime (). GetTimestamp (),
UpdatedTime : r . GetUpdateTime (). GetTimestamp (),
Version : r . GetVersion (),
AuthorizedActions : testAuthorizedActions ,
}
2024-06-25 13:05:52 -04:00
for _ , r := range r . GrantScopes {
ret . GrantScopeIds = append ( ret . GrantScopeIds , r . ScopeIdOrSpecial )
}
return ret
2023-12-15 11:49:59 -08:00
}
func TestListPagination ( t * testing . T ) {
// Set database read timeout to avoid duplicates in response
oldReadTimeout := globals . RefreshReadLookbackDuration
globals . RefreshReadLookbackDuration = 0
t . Cleanup ( func () {
globals . RefreshReadLookbackDuration = oldReadTimeout
})
ctx := context . Background ()
conn , _ := db . TestSetup ( t , "postgres" )
sqlDB , err := conn . SqlDB ( ctx )
require . NoError ( t , err )
wrapper := db . TestWrapper ( t )
kms := kms . TestKms ( t , conn , wrapper )
rw := db . New ( conn )
iamRepo := iam . TestRepo ( t , conn , wrapper )
iamRepoFn := func () ( * iam . Repository , error ) {
return iamRepo , nil
}
tokenRepoFn := func () ( * authtoken . Repository , error ) {
return authtoken . NewRepository ( ctx , rw , rw , kms )
}
serversRepoFn := func () ( * server . Repository , error ) {
return server . NewRepository ( ctx , rw , rw , kms )
}
tokenRepo , err := tokenRepoFn ()
require . NoError ( t , err )
// Run analyze to update postgres meta tables
_ , err = sqlDB . ExecContext ( ctx , "analyze" )
require . NoError ( t , err )
oNoRoles , pWithRoles := iam . TestScopes ( t , iamRepo , iam . WithSkipDefaultRoleCreation ( true ))
oWithRoles , pNoRoles := iam . TestScopes ( t , iamRepo , iam . WithSkipDefaultRoleCreation ( true ))
authMethod := password . TestAuthMethods ( t , conn , "global" , 1 )[ 0 ]
acct := password . TestAccount ( t , conn , authMethod . GetPublicId (), "test_user" )
u := iam . TestUser ( t , iamRepo , "global" , iam . WithAccountIds ( acct . PublicId ))
var allRoles [] * pb . Role
for _ , scope := range [] * iam . Scope { oWithRoles , oNoRoles , pWithRoles , pNoRoles } {
allowedRole := iam . TestRole ( t , conn , scope . GetPublicId ())
2024-01-17 23:54:49 -08:00
iam . TestRoleGrant ( t , conn , allowedRole . GetPublicId (), "ids=*;type=*;actions=*" )
2023-12-15 11:49:59 -08:00
iam . TestUserRole ( t , conn , allowedRole . GetPublicId (), u . GetPublicId ())
allRoles = append ( allRoles , roleToProto ( allowedRole ,
& scopes . ScopeInfo {
Id : scope . GetPublicId (),
ParentScopeId : scope . GetParentId (),
Type : scope . GetType (),
},
testAuthorizedActions ,
))
}
at , err := tokenRepo . CreateAuthToken ( ctx , u , acct . GetPublicId ())
require . NoError ( t , err )
// Test without anon user
requestInfo := authpb . RequestInfo {
TokenFormat : uint32 ( auth . AuthTokenTypeBearer ),
PublicId : at . GetPublicId (),
Token : at . GetToken (),
}
requestContext := context . WithValue ( context . Background (), requests . ContextRequestInformationKey , & requests . RequestContext {})
ctx = auth . NewVerifierContext ( requestContext , iamRepoFn , tokenRepoFn , serversRepoFn , kms , & requestInfo )
var safeToDeleteRole string
orgScopeInfo := & scopes . ScopeInfo { Id : oWithRoles . GetPublicId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()}
projScopeInfo := & scopes . ScopeInfo { Id : pWithRoles . GetPublicId (), Type : scope . Project . String (), ParentScopeId : pWithRoles . GetParentId ()}
for i := 0 ; i < 10 ; i ++ {
or := iam . TestRole ( t , conn , oWithRoles . GetPublicId ())
allRoles = append ( allRoles , roleToProto ( or , orgScopeInfo , testAuthorizedActions ))
pr := iam . TestRole ( t , conn , pWithRoles . GetPublicId ())
allRoles = append ( allRoles , roleToProto ( pr , projScopeInfo , testAuthorizedActions ))
safeToDeleteRole = pr . GetPublicId ()
}
slices . Reverse ( allRoles )
a , err := roles . NewService ( ctx , iamRepoFn , 1000 )
require . NoError ( t , err , "Couldn't create new user service." )
// Run analyze to update postgres estimates
_ , err = sqlDB . ExecContext ( context . Background (), "analyze" )
require . NoError ( t , err )
itemCount := uint32 ( len ( allRoles ))
testPageSize := int (( itemCount - 2 ) / 2 )
// Start paginating, recursively
req := & pbs . ListRolesRequest {
ScopeId : "global" ,
Recursive : true ,
Filter : "" ,
ListToken : "" ,
PageSize : uint32 ( testPageSize ),
}
got , err := a . ListRoles ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), testPageSize )
// Compare without comparing the list token
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListRolesResponse {
Items : allRoles [ 0 : testPageSize ],
ResponseType : "delta" ,
SortBy : "created_time" ,
SortDir : "desc" ,
RemovedIds : nil ,
// In addition to the added roles, there are the roles added
// by the test setup when specifying the permissions of the
// requester
EstItemCount : itemCount ,
},
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . Transform (),
protocmp . IgnoreFields ( & pbs . ListRolesResponse {}, "list_token" ),
),
)
// Request second page
req . ListToken = got . ListToken
got , err = a . ListRoles ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), testPageSize )
// Compare without comparing the list token
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListRolesResponse {
Items : allRoles [ testPageSize : testPageSize * 2 ],
ResponseType : "delta" ,
SortBy : "created_time" ,
SortDir : "desc" ,
RemovedIds : nil ,
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListRolesResponse {}, "list_token" ),
),
)
// Request rest of results
req . ListToken = got . ListToken
req . PageSize = 10
got , err = a . ListRoles ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), 2 )
// Compare without comparing the list token
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListRolesResponse {
Items : allRoles [ testPageSize * 2 :],
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
RemovedIds : nil ,
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListRolesResponse {}, "list_token" ),
),
)
// Update 2 roles and see them in the refresh
r1 := allRoles [ len ( allRoles ) - 1 ]
r1 . Description = wrapperspb . String ( "updated1" )
resp1 , err := a . UpdateRole ( ctx , & pbs . UpdateRoleRequest {
Id : r1 . GetId (),
Item : & pb . Role { Description : r1 . GetDescription (), Version : r1 . GetVersion ()},
UpdateMask : & field_mask . FieldMask { Paths : [] string { "description" }},
})
require . NoError ( t , err )
r1 . UpdatedTime = resp1 . GetItem (). GetUpdatedTime ()
r1 . Version = resp1 . GetItem (). GetVersion ()
allRoles = append ([] * pb . Role { r1 }, allRoles [: len ( allRoles ) - 1 ] ... )
r2 := allRoles [ len ( allRoles ) - 1 ]
r2 . Description = wrapperspb . String ( "updated2" )
resp2 , err := a . UpdateRole ( ctx , & pbs . UpdateRoleRequest {
Id : r2 . GetId (),
Item : & pb . Role { Description : r2 . GetDescription (), Version : r2 . GetVersion ()},
UpdateMask : & field_mask . FieldMask { Paths : [] string { "description" }},
})
require . NoError ( t , err )
r2 . UpdatedTime = resp2 . GetItem (). GetUpdatedTime ()
r2 . Version = resp2 . GetItem (). GetVersion ()
allRoles = append ([] * pb . Role { r2 }, allRoles [: len ( allRoles ) - 1 ] ... )
// Run analyze to update postgres estimates
_ , err = sqlDB . ExecContext ( ctx , "analyze" )
require . NoError ( t , err )
// Request updated results
req . ListToken = got . ListToken
req . PageSize = 1
got , err = a . ListRoles ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), 1 )
// Compare without comparing the list token
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListRolesResponse {
Items : [] * pb . Role { allRoles [ 0 ]},
ResponseType : "delta" ,
SortBy : "updated_time" ,
SortDir : "desc" ,
RemovedIds : nil ,
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListRolesResponse {}, "list_token" ),
),
)
// Get next page
req . ListToken = got . ListToken
got , err = a . ListRoles ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), 1 )
// Compare without comparing the list token
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListRolesResponse {
Items : [] * pb . Role { allRoles [ 1 ]},
ResponseType : "complete" ,
SortBy : "updated_time" ,
SortDir : "desc" ,
RemovedIds : nil ,
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListRolesResponse {}, "list_token" ),
),
)
// Request new page with filter requiring looping
// to fill the page.
req . ListToken = ""
req . PageSize = 1
req . Filter = fmt . Sprintf ( `"/item/id"==%q or "/item/id"==%q` , allRoles [ len ( allRoles ) - 2 ]. Id , allRoles [ len ( allRoles ) - 1 ]. Id )
got , err = a . ListRoles ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), 1 )
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListRolesResponse {
Items : [] * pb . Role { allRoles [ len ( allRoles ) - 2 ]},
ResponseType : "delta" ,
SortBy : "created_time" ,
SortDir : "desc" ,
// Should be empty again
RemovedIds : nil ,
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListRolesResponse {}, "list_token" ),
),
)
req . ListToken = got . ListToken
// Get the second page
got , err = a . ListRoles ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), 1 )
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListRolesResponse {
Items : [] * pb . Role { allRoles [ len ( allRoles ) - 1 ]},
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
RemovedIds : nil ,
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListRolesResponse {}, "list_token" ),
),
)
_ , err = iamRepo . DeleteRole ( ctx , safeToDeleteRole )
require . NoError ( t , err )
req . ListToken = got . ListToken
got , err = a . ListRoles ( ctx , req )
require . NoError ( t , err )
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListRolesResponse {
Items : nil ,
ResponseType : "complete" ,
SortBy : "updated_time" ,
SortDir : "desc" ,
RemovedIds : [] string { safeToDeleteRole },
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListRolesResponse {}, "list_token" ),
),
)
2024-02-15 09:26:29 -08:00
// Create unauthenticated user
unauthAt := authtoken . TestAuthToken ( t , conn , kms , oWithRoles . GetPublicId ())
unauthR := iam . TestRole ( t , conn , pWithRoles . GetPublicId ())
_ = iam . TestUserRole ( t , conn , unauthR . GetPublicId (), unauthAt . GetIamUserId ())
// Make a request with the unauthenticated user,
// ensure the response contains the pagination parameters.
requestInfo = authpb . RequestInfo {
TokenFormat : uint32 ( auth . AuthTokenTypeBearer ),
PublicId : unauthAt . GetPublicId (),
Token : unauthAt . GetToken (),
}
requestContext = context . WithValue ( context . Background (), requests . ContextRequestInformationKey , & requests . RequestContext {})
ctx = auth . NewVerifierContext ( requestContext , iamRepoFn , tokenRepoFn , serversRepoFn , kms , & requestInfo )
_ , err = a . ListRoles ( ctx , & pbs . ListRolesRequest {
ScopeId : "global" ,
Recursive : true ,
})
require . Error ( t , err )
assert . ErrorIs ( t , handlers . ForbiddenError (), err )
2023-12-15 11:49:59 -08:00
}
2020-06-22 06:56:27 -07:00
func TestDelete ( t * testing . T ) {
2021-03-25 03:15:43 -04:00
or , pr , repoFn := createDefaultRolesAndRepo ( t )
2020-06-22 06:56:27 -07:00
2023-12-15 11:49:59 -08:00
s , err := roles . NewService ( context . Background (), repoFn , 1000 )
2020-09-23 08:10:27 -07:00
require . NoError ( t , err , "Error when getting new role service." )
2020-06-22 06:56:27 -07:00
cases := [] struct {
name string
2020-07-22 00:14:28 -04:00
scopeId string
2020-06-22 06:56:27 -07:00
req * pbs . DeleteRoleRequest
res * pbs . DeleteRoleResponse
2020-09-23 08:10:27 -07:00
err error
2020-06-22 06:56:27 -07:00
}{
{
2020-07-22 00:14:28 -04:00
name : "Delete an Existing Role" ,
2021-03-25 03:15:43 -04:00
scopeId : or . GetScopeId (),
2020-06-22 06:56:27 -07:00
req : & pbs . DeleteRoleRequest {
2020-07-22 00:14:28 -04:00
Id : or . GetPublicId (),
2020-06-22 06:56:27 -07:00
},
},
{
2020-07-22 00:14:28 -04:00
name : "Delete bad role id" ,
2021-03-25 03:15:43 -04:00
scopeId : or . GetScopeId (),
2020-06-22 06:56:27 -07:00
req : & pbs . DeleteRoleRequest {
2023-03-10 15:06:39 -05:00
Id : globals . RolePrefix + "_doesntexis" ,
2020-06-22 06:56:27 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . NotFound ),
2020-06-22 06:56:27 -07:00
},
{
2020-07-22 00:14:28 -04:00
name : "Bad Role Id formatting" ,
2021-03-25 03:15:43 -04:00
scopeId : or . GetScopeId (),
2020-06-22 06:56:27 -07:00
req : & pbs . DeleteRoleRequest {
2020-07-22 00:14:28 -04:00
Id : "bad_format" ,
2020-06-22 06:56:27 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-22 06:56:27 -07:00
},
2020-06-29 11:12:40 -07:00
{
2020-07-22 00:14:28 -04:00
name : "Project Scoped Delete an Existing Role" ,
2021-03-25 03:15:43 -04:00
scopeId : pr . GetScopeId (),
2020-06-29 11:12:40 -07:00
req : & pbs . DeleteRoleRequest {
2020-07-22 00:14:28 -04:00
Id : pr . GetPublicId (),
2020-06-29 11:12:40 -07:00
},
},
{
2020-07-22 00:14:28 -04:00
name : "Project Scoped Delete bad Role id" ,
2021-03-25 03:15:43 -04:00
scopeId : pr . GetScopeId (),
2020-06-29 11:12:40 -07:00
req : & pbs . DeleteRoleRequest {
2023-03-10 15:06:39 -05:00
Id : globals . RolePrefix + "_doesntexis" ,
2020-06-29 11:12:40 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . NotFound ),
2020-06-29 11:12:40 -07:00
},
2020-06-22 06:56:27 -07:00
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2021-03-25 03:15:43 -04:00
got , gErr := s . DeleteRole ( auth . DisabledAuthTestContext ( repoFn , tc . scopeId ), tc . req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . NotNil ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "DeleteRole(%+v) got error %v, wanted %v" , tc . req , gErr , tc . err )
}
2020-06-22 06:56:27 -07:00
assert . EqualValuesf ( tc . res , got , "DeleteRole(%q) got response %q, wanted %q" , tc . req , got , tc . res )
})
}
}
func TestDelete_twice ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2021-03-25 03:15:43 -04:00
or , pr , repoFn := createDefaultRolesAndRepo ( t )
2020-06-22 06:56:27 -07:00
2023-12-15 11:49:59 -08:00
s , err := roles . NewService ( context . Background (), repoFn , 1000 )
2020-06-22 06:56:27 -07:00
require . NoError ( err , "Error when getting new role service" )
req := & pbs . DeleteRoleRequest {
2020-07-22 00:14:28 -04:00
Id : or . GetPublicId (),
2020-06-22 06:56:27 -07:00
}
2021-03-25 03:15:43 -04:00
ctx := auth . DisabledAuthTestContext ( repoFn , or . GetScopeId ())
2020-09-08 23:57:26 -04:00
_ , gErr := s . DeleteRole ( ctx , req )
2020-06-22 06:56:27 -07:00
assert . NoError ( gErr , "First attempt" )
2020-09-08 23:57:26 -04:00
_ , gErr = s . DeleteRole ( ctx , req )
2020-09-04 14:48:11 -07:00
assert . Error ( gErr , "Second attempt" )
2020-09-23 08:10:27 -07:00
assert . True ( errors . Is ( gErr , handlers . ApiErrorWithCode ( codes . NotFound )), "Expected permission denied for the second delete." )
2020-06-29 11:12:40 -07:00
projReq := & pbs . DeleteRoleRequest {
2020-07-22 00:14:28 -04:00
Id : pr . GetPublicId (),
2020-06-29 11:12:40 -07:00
}
2021-03-25 03:15:43 -04:00
ctx = auth . DisabledAuthTestContext ( repoFn , pr . GetScopeId ())
2020-09-08 23:57:26 -04:00
_ , gErr = s . DeleteRole ( ctx , projReq )
2020-06-29 11:12:40 -07:00
assert . NoError ( gErr , "First attempt" )
2020-09-08 23:57:26 -04:00
_ , gErr = s . DeleteRole ( ctx , projReq )
2020-09-04 14:48:11 -07:00
assert . Error ( gErr , "Second attempt" )
2020-09-23 08:10:27 -07:00
assert . True ( errors . Is ( gErr , handlers . ApiErrorWithCode ( codes . NotFound )), "Expected permission denied for the second delete." )
2020-06-22 06:56:27 -07:00
}
func TestCreate ( t * testing . T ) {
2021-03-25 03:15:43 -04:00
defaultOrgRole , defaultProjRole , repoFn := createDefaultRolesAndRepo ( t )
2021-04-23 09:13:37 -05:00
defaultCreated := defaultOrgRole . GetCreateTime (). GetTimestamp (). AsTime ()
2020-07-22 00:14:28 -04:00
toMerge := & pbs . CreateRoleRequest {}
2020-06-22 06:56:27 -07:00
cases := [] struct {
2020-09-23 08:10:27 -07:00
name string
req * pbs . CreateRoleRequest
res * pbs . CreateRoleResponse
err error
2020-06-22 06:56:27 -07:00
}{
{
2020-09-02 19:43:41 -07:00
name : "Create a valid Role" ,
2020-06-22 06:56:27 -07:00
req : & pbs . CreateRoleRequest { Item : & pb . Role {
2024-06-17 12:09:33 -07:00
ScopeId : defaultOrgRole . GetScopeId (),
Name : & wrapperspb . StringValue { Value : "name" },
Description : & wrapperspb . StringValue { Value : "desc" },
2020-06-22 06:56:27 -07:00
}},
res : & pbs . CreateRoleResponse {
2023-03-10 15:06:39 -05:00
Uri : fmt . Sprintf ( "roles/%s_" , globals . RolePrefix ),
2020-06-29 11:12:40 -07:00
Item : & pb . Role {
2021-01-20 10:53:01 -05:00
ScopeId : defaultOrgRole . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : defaultOrgRole . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2021-01-20 10:53:01 -05:00
Name : & wrapperspb . StringValue { Value : "name" },
Description : & wrapperspb . StringValue { Value : "desc" },
2024-06-17 12:09:33 -07:00
GrantScopeIds : [] string { globals . GrantScopeThis },
2024-01-23 14:33:09 -05:00
Version : 2 ,
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-29 11:12:40 -07:00
},
},
},
2020-09-03 08:02:30 -07:00
{
name : "Create a valid Global Role" ,
req : & pbs . CreateRoleRequest { Item : & pb . Role {
2024-06-17 12:09:33 -07:00
ScopeId : scope . Global . String (),
Name : & wrapperspb . StringValue { Value : "name" },
Description : & wrapperspb . StringValue { Value : "desc" },
2020-09-03 08:02:30 -07:00
}},
res : & pbs . CreateRoleResponse {
2023-03-10 15:06:39 -05:00
Uri : fmt . Sprintf ( "roles/%s_" , globals . RolePrefix ),
2020-09-03 08:02:30 -07:00
Item : & pb . Role {
2021-01-20 10:53:01 -05:00
ScopeId : scope . Global . String (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : scope . Global . String (), Type : scope . Global . String (), Name : scope . Global . String (), Description : "Global Scope" },
2021-01-20 10:53:01 -05:00
Name : & wrapperspb . StringValue { Value : "name" },
Description : & wrapperspb . StringValue { Value : "desc" },
2024-06-17 12:09:33 -07:00
GrantScopeIds : [] string { globals . GrantScopeThis },
2024-01-23 14:33:09 -05:00
Version : 2 ,
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-09-03 08:02:30 -07:00
},
},
},
2020-06-29 11:12:40 -07:00
{
2020-09-02 19:43:41 -07:00
name : "Create a valid Project Scoped Role" ,
2020-06-29 11:12:40 -07:00
req : & pbs . CreateRoleRequest {
Item : & pb . Role {
2020-09-02 19:43:41 -07:00
ScopeId : defaultProjRole . GetScopeId (),
2020-06-29 11:12:40 -07:00
Name : & wrapperspb . StringValue { Value : "name" },
Description : & wrapperspb . StringValue { Value : "desc" },
},
},
res : & pbs . CreateRoleResponse {
2023-03-10 15:06:39 -05:00
Uri : fmt . Sprintf ( "roles/%s_" , globals . RolePrefix ),
2020-06-22 06:56:27 -07:00
Item : & pb . Role {
2021-01-20 10:53:01 -05:00
ScopeId : defaultProjRole . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : defaultProjRole . GetScopeId (), Type : scope . Project . String (), ParentScopeId : defaultOrgRole . GetScopeId ()},
2021-01-20 10:53:01 -05:00
Name : & wrapperspb . StringValue { Value : "name" },
Description : & wrapperspb . StringValue { Value : "desc" },
2024-01-23 14:33:09 -05:00
GrantScopeIds : [] string { globals . GrantScopeThis },
Version : 2 ,
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-22 06:56:27 -07:00
},
},
},
{
2020-09-02 19:43:41 -07:00
name : "Can't specify Id" ,
2020-06-22 06:56:27 -07:00
req : & pbs . CreateRoleRequest { Item : & pb . Role {
2020-09-02 19:43:41 -07:00
ScopeId : defaultProjRole . GetScopeId (),
2023-03-10 15:06:39 -05:00
Id : globals . RolePrefix + "_notallowed" ,
2020-06-22 06:56:27 -07:00
}},
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-22 06:56:27 -07:00
},
{
2020-09-02 19:43:41 -07:00
name : "Can't specify Created Time" ,
2020-06-22 06:56:27 -07:00
req : & pbs . CreateRoleRequest { Item : & pb . Role {
2020-09-02 19:43:41 -07:00
ScopeId : defaultProjRole . GetScopeId (),
2021-04-23 09:13:37 -05:00
CreatedTime : timestamppb . Now (),
2020-06-22 06:56:27 -07:00
}},
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-22 06:56:27 -07:00
},
{
2020-09-02 19:43:41 -07:00
name : "Can't specify Update Time" ,
2020-06-22 06:56:27 -07:00
req : & pbs . CreateRoleRequest { Item : & pb . Role {
2020-09-02 19:43:41 -07:00
ScopeId : defaultProjRole . GetScopeId (),
2021-04-23 09:13:37 -05:00
UpdatedTime : timestamppb . Now (),
2020-06-22 06:56:27 -07:00
}},
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-22 06:56:27 -07:00
},
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2020-06-22 06:56:27 -07:00
req := proto . Clone ( toMerge ).( * pbs . CreateRoleRequest )
proto . Merge ( req , tc . req )
2023-12-15 11:49:59 -08:00
s , err := roles . NewService ( context . Background (), repoFn , 1000 )
2020-06-22 06:56:27 -07:00
require . NoError ( err , "Error when getting new role service." )
2021-03-25 03:15:43 -04:00
got , gErr := s . CreateRole ( auth . DisabledAuthTestContext ( repoFn , tc . req . GetItem (). GetScopeId ()), req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . NotNil ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "CreateRole(%+v) got error %v, wanted %v" , req , gErr , tc . err )
}
2020-06-22 06:56:27 -07:00
if got != nil {
2020-08-05 10:19:55 -07:00
assert . Contains ( got . GetUri (), tc . res . Uri )
2023-03-10 15:06:39 -05:00
assert . True ( strings . HasPrefix ( got . GetItem (). GetId (), globals . RolePrefix + "_" ), "Expected %q to have the prefix %q" , got . GetItem (). GetId (), globals . RolePrefix + "_" )
2021-04-23 09:13:37 -05:00
gotCreateTime := got . GetItem (). GetCreatedTime (). AsTime ()
gotUpdateTime := got . GetItem (). GetUpdatedTime (). AsTime ()
2020-06-22 06:56:27 -07:00
// Verify it is a role created after the test setup's default role
assert . True ( gotCreateTime . After ( defaultCreated ), "New role should have been created after default role. Was created %v, which is after %v" , gotCreateTime , defaultCreated )
assert . True ( gotUpdateTime . After ( defaultCreated ), "New role should have been updated after default role. Was updated %v, which is after %v" , gotUpdateTime , defaultCreated )
// Clear all values which are hard to compare against.
got . Uri , tc . res . Uri = "" , ""
got . Item . Id , tc . res . Item . Id = "" , ""
got . Item . CreatedTime , got . Item . UpdatedTime , tc . res . Item . CreatedTime , tc . res . Item . UpdatedTime = nil , nil , nil , nil
}
2023-10-31 13:44:17 +00:00
assert . Empty ( cmp . Diff (
got ,
tc . res ,
protocmp . Transform (),
cmpopts . SortSlices ( func ( a , b string ) bool {
return a < b
}),
), "CreateRole(%q) got response\n%q, wanted\n%q" , req , got , tc . res )
2020-06-22 06:56:27 -07:00
})
}
}
func TestUpdate ( t * testing . T ) {
2023-06-06 17:09:08 -04:00
ctx := context . Background ()
2024-01-17 23:54:49 -08:00
grantString := "ids=*;type=*;actions=*"
2024-09-17 10:07:43 -04:00
g , err := perms . Parse ( context . Background (), perms . GrantTuple { RoleScopeId : "global" , GrantScopeId : "global" , Grant : grantString })
2020-07-17 09:31:10 -07:00
require . NoError ( t , err )
_ , actions := g . Actions ()
grant := & pb . Grant {
Raw : grantString ,
Canonical : g . CanonicalString (),
Json : & pb . GrantJson {
Id : g . Id (),
2023-06-06 16:13:44 -04:00
Ids : g . Ids (),
2020-07-17 09:31:10 -07:00
Type : g . Type (). String (),
Actions : actions ,
},
}
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-07-17 09:31:10 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-07-17 09:31:10 -07:00
}
2020-08-19 16:47:18 -04:00
o , p := iam . TestScopes ( t , iamRepo )
u := iam . TestUser ( t , iamRepo , o . GetPublicId ())
2020-07-17 09:31:10 -07:00
2024-01-23 14:33:09 -05:00
or := iam . TestRole ( t , conn , o . GetPublicId (), iam . WithDescription ( "default" ), iam . WithName ( "default" ), iam . WithGrantScopeIds ([] string { p . GetPublicId ()}))
2020-07-17 09:31:10 -07:00
_ = iam . TestRoleGrant ( t , conn , or . GetPublicId (), grantString )
_ = iam . TestUserRole ( t , conn , or . GetPublicId (), u . GetPublicId ())
pr := iam . TestRole ( t , conn , p . GetPublicId (), iam . WithDescription ( "default" ), iam . WithName ( "default" ))
_ = iam . TestRoleGrant ( t , conn , pr . GetPublicId (), grantString )
_ = iam . TestUserRole ( t , conn , pr . GetPublicId (), u . GetPublicId ())
principal := & pb . Principal {
Id : u . GetPublicId (),
Type : iam . UserRoleType . String (),
ScopeId : u . GetScopeId (),
}
2024-01-23 14:33:09 -05:00
orVersion := or . Version
prVersion := pr . Version
2020-08-07 12:55:02 -04:00
2023-12-15 11:49:59 -08:00
tested , err := roles . NewService ( ctx , repoFn , 0 )
2020-07-17 09:31:10 -07:00
require . NoError ( t , err , "Error when getting new role service." )
2020-06-22 06:56:27 -07:00
2020-08-07 12:55:02 -04:00
resetRoles := func ( proj bool ) {
2020-06-22 06:56:27 -07:00
repo , err := repoFn ()
2020-07-17 09:31:10 -07:00
require . NoError ( t , err , "Couldn't get a new repo" )
2020-08-07 12:55:02 -04:00
if proj {
2024-01-23 14:33:09 -05:00
pr , _ , _ , _ , _ , err = repo . UpdateRole ( context . Background (), pr , prVersion , [] string { "Name" , "Description" })
2020-08-07 12:55:02 -04:00
require . NoError ( t , err , "Failed to reset the role" )
2024-01-23 14:33:09 -05:00
prVersion = pr . Version
2020-08-07 12:55:02 -04:00
} else {
2024-01-23 14:33:09 -05:00
or , _ , _ , _ , _ , err = repo . UpdateRole ( context . Background (), or , orVersion , [] string { "Name" , "Description" })
2020-08-07 12:55:02 -04:00
require . NoError ( t , err , "Failed to reset the role" )
2024-01-23 14:33:09 -05:00
orVersion = or . Version
2020-08-07 12:55:02 -04:00
}
2020-06-22 06:56:27 -07:00
}
2021-04-23 09:13:37 -05:00
created := or . GetCreateTime (). GetTimestamp (). AsTime ()
2020-06-22 06:56:27 -07:00
toMerge := & pbs . UpdateRoleRequest {
2020-07-22 00:14:28 -04:00
Id : or . GetPublicId (),
2020-06-22 06:56:27 -07:00
}
cases := [] struct {
name string
2020-07-22 00:14:28 -04:00
scopeId string
2020-06-22 06:56:27 -07:00
req * pbs . UpdateRoleRequest
res * pbs . UpdateRoleResponse
2020-09-23 08:10:27 -07:00
err error
2020-06-22 06:56:27 -07:00
}{
{
2020-07-22 00:14:28 -04:00
name : "Update an Existing Role" ,
scopeId : or . GetScopeId (),
2020-06-22 06:56:27 -07:00
req : & pbs . UpdateRoleRequest {
UpdateMask : & field_mask . FieldMask {
2024-01-23 14:33:09 -05:00
Paths : [] string { "name" , "description" },
2020-06-22 06:56:27 -07:00
},
Item : & pb . Role {
2024-01-23 14:33:09 -05:00
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
2020-06-22 06:56:27 -07:00
},
},
res : & pbs . UpdateRoleResponse {
Item : & pb . Role {
2021-01-20 10:53:01 -05:00
Id : or . GetPublicId (),
ScopeId : or . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : or . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2021-01-20 10:53:01 -05:00
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
CreatedTime : or . GetCreateTime (). GetTimestamp (),
2024-01-23 14:33:09 -05:00
GrantScopeIds : [] string { p . GetPublicId ()},
2021-01-20 10:53:01 -05:00
GrantStrings : [] string { grant . GetRaw ()},
Grants : [] * pb . Grant { grant },
PrincipalIds : [] string { u . GetPublicId ()},
Principals : [] * pb . Principal { principal },
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-29 11:12:40 -07:00
},
},
},
{
2020-07-22 00:14:28 -04:00
name : "Multiple Paths in single string" ,
scopeId : or . GetScopeId (),
2020-06-29 11:12:40 -07:00
req : & pbs . UpdateRoleRequest {
UpdateMask : & field_mask . FieldMask {
2024-06-17 12:09:33 -07:00
Paths : [] string { "name,description" },
2020-06-29 11:12:40 -07:00
},
Item : & pb . Role {
2024-06-17 12:09:33 -07:00
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
2020-06-29 11:12:40 -07:00
},
},
res : & pbs . UpdateRoleResponse {
Item : & pb . Role {
2021-01-20 10:53:01 -05:00
Id : or . GetPublicId (),
ScopeId : or . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : or . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2021-01-20 10:53:01 -05:00
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
CreatedTime : or . GetCreateTime (). GetTimestamp (),
2024-06-17 12:09:33 -07:00
GrantScopeIds : [] string { p . GetPublicId ()},
2021-01-20 10:53:01 -05:00
GrantStrings : [] string { grant . GetRaw ()},
Grants : [] * pb . Grant { grant },
PrincipalIds : [] string { u . GetPublicId ()},
Principals : [] * pb . Principal { principal },
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-29 11:12:40 -07:00
},
},
},
{
2020-07-22 00:14:28 -04:00
name : "Update an Existing Project Scoped Role" ,
scopeId : pr . GetScopeId (),
2020-06-29 11:12:40 -07:00
req : & pbs . UpdateRoleRequest {
2020-07-22 00:14:28 -04:00
Id : pr . GetPublicId (),
2020-06-29 11:12:40 -07:00
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "name" , "description" },
},
Item : & pb . Role {
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
},
},
res : & pbs . UpdateRoleResponse {
Item : & pb . Role {
2021-01-20 10:53:01 -05:00
Id : pr . GetPublicId (),
ScopeId : pr . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : pr . GetScopeId (), Type : scope . Project . String (), ParentScopeId : or . GetScopeId ()},
2021-01-20 10:53:01 -05:00
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
CreatedTime : pr . GetCreateTime (). GetTimestamp (),
2024-01-23 14:33:09 -05:00
GrantScopeIds : [] string { globals . GrantScopeThis },
2021-01-20 10:53:01 -05:00
GrantStrings : [] string { grant . GetRaw ()},
Grants : [] * pb . Grant { grant },
PrincipalIds : [] string { u . GetPublicId ()},
Principals : [] * pb . Principal { principal },
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-22 06:56:27 -07:00
},
},
},
{
2020-07-22 00:14:28 -04:00
name : "Multiple Paths in single string" ,
scopeId : pr . GetScopeId (),
2020-06-22 06:56:27 -07:00
req : & pbs . UpdateRoleRequest {
2020-07-22 00:14:28 -04:00
Id : pr . GetPublicId (),
2020-06-22 06:56:27 -07:00
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "name,description" },
},
Item : & pb . Role {
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
},
},
res : & pbs . UpdateRoleResponse {
Item : & pb . Role {
2021-01-20 10:53:01 -05:00
Id : pr . GetPublicId (),
ScopeId : pr . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : pr . GetScopeId (), Type : scope . Project . String (), ParentScopeId : or . GetScopeId ()},
2021-01-20 10:53:01 -05:00
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
CreatedTime : pr . GetCreateTime (). GetTimestamp (),
2024-01-23 14:33:09 -05:00
GrantScopeIds : [] string { globals . GrantScopeThis },
2021-01-20 10:53:01 -05:00
GrantStrings : [] string { grant . GetRaw ()},
Grants : [] * pb . Grant { grant },
PrincipalIds : [] string { u . GetPublicId ()},
Principals : [] * pb . Principal { principal },
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-22 06:56:27 -07:00
},
},
},
{
name : "No Update Mask" ,
req : & pbs . UpdateRoleRequest {
Item : & pb . Role {
Name : & wrapperspb . StringValue { Value : "updated name" },
Description : & wrapperspb . StringValue { Value : "updated desc" },
},
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-22 06:56:27 -07:00
},
{
2020-07-22 00:14:28 -04:00
name : "No Paths in Mask" ,
scopeId : or . GetScopeId (),
2020-06-22 06:56:27 -07:00
req : & pbs . UpdateRoleRequest {
UpdateMask : & field_mask . FieldMask { Paths : [] string {}},
Item : & pb . Role {
Name : & wrapperspb . StringValue { Value : "updated name" },
Description : & wrapperspb . StringValue { Value : "updated desc" },
},
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-22 06:56:27 -07:00
},
{
2024-02-16 08:30:16 -05:00
name : "Only non-existent paths in Mask" ,
2020-07-22 00:14:28 -04:00
scopeId : or . GetScopeId (),
2020-06-22 06:56:27 -07:00
req : & pbs . UpdateRoleRequest {
2024-02-16 08:30:16 -05:00
UpdateMask : & field_mask . FieldMask { Paths : [] string { "nonexistent_field" }},
2020-06-22 06:56:27 -07:00
Item : & pb . Role {
Name : & wrapperspb . StringValue { Value : "updated name" },
Description : & wrapperspb . StringValue { Value : "updated desc" },
},
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-22 06:56:27 -07:00
},
{
2020-07-22 00:14:28 -04:00
name : "Unset Name" ,
scopeId : or . GetScopeId (),
2020-06-22 06:56:27 -07:00
req : & pbs . UpdateRoleRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "name" },
},
Item : & pb . Role {
Description : & wrapperspb . StringValue { Value : "ignored" },
},
},
res : & pbs . UpdateRoleResponse {
Item : & pb . Role {
2021-01-20 10:53:01 -05:00
Id : or . GetPublicId (),
ScopeId : or . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : or . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2021-01-20 10:53:01 -05:00
Description : & wrapperspb . StringValue { Value : "default" },
CreatedTime : or . GetCreateTime (). GetTimestamp (),
2024-06-17 12:09:33 -07:00
GrantScopeIds : [] string { p . GetPublicId ()},
2021-01-20 10:53:01 -05:00
GrantStrings : [] string { grant . GetRaw ()},
Grants : [] * pb . Grant { grant },
PrincipalIds : [] string { u . GetPublicId ()},
Principals : [] * pb . Principal { principal },
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-22 06:56:27 -07:00
},
},
},
{
2020-07-22 00:14:28 -04:00
name : "Update Only Name" ,
scopeId : or . GetScopeId (),
2020-06-22 06:56:27 -07:00
req : & pbs . UpdateRoleRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "name" },
},
Item : & pb . Role {
Name : & wrapperspb . StringValue { Value : "updated" },
Description : & wrapperspb . StringValue { Value : "ignored" },
},
},
res : & pbs . UpdateRoleResponse {
Item : & pb . Role {
2021-01-20 10:53:01 -05:00
Id : or . GetPublicId (),
ScopeId : or . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : or . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2021-01-20 10:53:01 -05:00
Name : & wrapperspb . StringValue { Value : "updated" },
Description : & wrapperspb . StringValue { Value : "default" },
CreatedTime : or . GetCreateTime (). GetTimestamp (),
2024-06-17 12:09:33 -07:00
GrantScopeIds : [] string { p . GetPublicId ()},
2021-01-20 10:53:01 -05:00
GrantStrings : [] string { grant . GetRaw ()},
Grants : [] * pb . Grant { grant },
PrincipalIds : [] string { u . GetPublicId ()},
Principals : [] * pb . Principal { principal },
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-22 06:56:27 -07:00
},
},
},
{
2020-07-22 00:14:28 -04:00
name : "Update Only Description" ,
scopeId : or . GetScopeId (),
2020-06-22 06:56:27 -07:00
req : & pbs . UpdateRoleRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "description" },
},
Item : & pb . Role {
Name : & wrapperspb . StringValue { Value : "ignored" },
Description : & wrapperspb . StringValue { Value : "notignored" },
},
},
res : & pbs . UpdateRoleResponse {
Item : & pb . Role {
2021-01-20 10:53:01 -05:00
Id : or . GetPublicId (),
ScopeId : or . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : or . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2021-01-20 10:53:01 -05:00
Name : & wrapperspb . StringValue { Value : "default" },
Description : & wrapperspb . StringValue { Value : "notignored" },
CreatedTime : or . GetCreateTime (). GetTimestamp (),
2024-06-17 12:09:33 -07:00
GrantScopeIds : [] string { p . GetPublicId ()},
2021-01-20 10:53:01 -05:00
GrantStrings : [] string { grant . GetRaw ()},
Grants : [] * pb . Grant { grant },
PrincipalIds : [] string { u . GetPublicId ()},
Principals : [] * pb . Principal { principal },
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-22 06:56:27 -07:00
},
},
},
{
name : "Update a Non Existing Role" ,
req : & pbs . UpdateRoleRequest {
2023-03-10 15:06:39 -05:00
Id : globals . RolePrefix + "_DoesntExis" ,
2020-06-22 06:56:27 -07:00
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "description" },
},
Item : & pb . Role {
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
},
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . NotFound ),
2020-06-22 06:56:27 -07:00
},
{
name : "Cant change Id" ,
req : & pbs . UpdateRoleRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "id" },
},
Item : & pb . Role {
2023-03-10 15:06:39 -05:00
Id : globals . RolePrefix + "_somethinge" ,
2020-06-22 06:56:27 -07:00
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "new desc" },
2021-01-07 10:02:32 -05:00
},
},
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-22 06:56:27 -07:00
},
{
name : "Cant specify Created Time" ,
req : & pbs . UpdateRoleRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "created_time" },
},
Item : & pb . Role {
2021-04-23 09:13:37 -05:00
CreatedTime : timestamppb . Now (),
2020-06-22 06:56:27 -07:00
},
},
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-22 06:56:27 -07:00
},
{
name : "Cant specify Updated Time" ,
req : & pbs . UpdateRoleRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "updated_time" },
},
Item : & pb . Role {
2021-04-23 09:13:37 -05:00
UpdatedTime : timestamppb . Now (),
2020-06-22 06:56:27 -07:00
},
},
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-22 06:56:27 -07:00
},
2020-07-17 09:31:10 -07:00
{
name : "Cant specify grants" ,
req : & pbs . UpdateRoleRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "grants" },
},
Item : & pb . Role {
GrantStrings : [] string { "anything" },
},
},
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-07-17 09:31:10 -07:00
},
{
name : "Cant specify principals" ,
req : & pbs . UpdateRoleRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "principal_ids" },
},
Item : & pb . Role {
PrincipalIds : [] string { "u_0987654321" },
},
},
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-07-17 09:31:10 -07:00
},
2020-06-22 06:56:27 -07:00
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
2020-08-07 12:55:02 -04:00
ver := orVersion
if tc . req . Id == pr . PublicId {
ver = prVersion
}
2020-08-18 17:38:38 -07:00
tc . req . Item . Version = ver
2020-08-07 12:55:02 -04:00
2020-07-17 09:31:10 -07:00
assert , require := assert . New ( t ), require . New ( t )
2020-06-22 06:56:27 -07:00
req := proto . Clone ( toMerge ).( * pbs . UpdateRoleRequest )
proto . Merge ( req , tc . req )
2021-03-25 03:15:43 -04:00
got , gErr := tested . UpdateRole ( auth . DisabledAuthTestContext ( repoFn , tc . scopeId ), req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "UpdateRole(%+v) got error %v, wanted %v" , req , gErr , tc . err )
}
2020-06-22 06:56:27 -07:00
2020-09-23 08:10:27 -07:00
if tc . err == nil {
2020-08-07 12:55:02 -04:00
defer resetRoles ( req . Id == pr . PublicId )
}
2020-06-22 06:56:27 -07:00
if got != nil {
assert . NotNilf ( tc . res , "Expected UpdateRole response to be nil, but was %v" , got )
2021-04-23 09:13:37 -05:00
gotUpdateTime := got . GetItem (). GetUpdatedTime (). AsTime ()
2020-06-22 06:56:27 -07:00
require . NoError ( err , "Error converting proto to timestamp" )
// Verify it is a role updated after it was created
assert . True ( gotUpdateTime . After ( created ), "Updated role should have been updated after it's creation. Was updated %v, which is after %v" , gotUpdateTime , created )
2024-01-23 14:33:09 -05:00
// Clear or set all values which are hard to compare against.
2020-06-22 06:56:27 -07:00
got . Item . UpdatedTime , tc . res . Item . UpdatedTime = nil , nil
2024-01-23 14:33:09 -05:00
tc . res . Item . Version = got . Item . Version
2020-07-10 11:21:11 -07:00
2024-01-23 14:33:09 -05:00
if req . Id == or . PublicId {
orVersion = got . Item . Version
} else {
prVersion = got . Item . Version
}
2020-06-22 06:56:27 -07:00
}
2023-10-31 13:44:17 +00:00
assert . Empty ( cmp . Diff (
got ,
tc . res ,
protocmp . Transform (),
cmpopts . SortSlices ( func ( a , b string ) bool {
return a < b
}),
), "UpdateRole(%q) got response\n%q,\nwanted\n%q" , req , got , tc . res )
2020-06-22 06:56:27 -07:00
})
}
}
2020-07-10 11:21:11 -07:00
func TestAddPrincipal ( t * testing . T ) {
2023-06-06 17:09:08 -04:00
ctx := context . Background ()
2020-07-10 11:21:11 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-07-10 11:21:11 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-07-10 11:21:11 -07:00
}
2021-06-04 09:44:57 -05:00
o , p := iam . TestScopes ( t , iamRepo )
2023-12-15 11:49:59 -08:00
s , err := roles . NewService ( ctx , repoFn , 0 )
2020-07-10 17:42:47 -07:00
require . NoError ( t , err , "Error when getting new role service." )
2020-07-10 11:21:11 -07:00
2021-06-04 09:44:57 -05:00
kmsCache := kms . TestKms ( t , conn , wrap )
databaseWrapper , err := kmsCache . GetWrapper ( ctx , o . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
authMethod := oidc . TestAuthMethod (
t , conn , databaseWrapper , o . GetPublicId (), oidc . ActivePrivateState ,
"alice-rp" , "fido" ,
oidc . WithSigningAlgs ( oidc . RS256 ),
oidc . WithIssuer ( oidc . TestConvertToUrls ( t , "https://www.alice.com" )[ 0 ]),
oidc . WithApiUrl ( oidc . TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]),
)
2023-06-26 17:05:54 -04:00
ldapAuthMethod := ldap . TestAuthMethod ( t , conn , databaseWrapper , o . PublicId , [] string { "ldaps://ldap1" })
ldapManagedGroup := ldap . TestManagedGroup ( t , conn , ldapAuthMethod , [] string { "admin" })
2020-07-10 17:42:47 -07:00
users := [] * iam . User {
2020-08-19 16:47:18 -04:00
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
2020-07-10 17:42:47 -07:00
}
groups := [] * iam . Group {
iam . TestGroup ( t , conn , o . GetPublicId ()),
iam . TestGroup ( t , conn , o . GetPublicId ()),
iam . TestGroup ( t , conn , o . GetPublicId ()),
}
2021-06-04 09:44:57 -05:00
managedGroups := [] * oidc . ManagedGroup {
oidc . TestManagedGroup ( t , conn , authMethod , oidc . TestFakeManagedGroupFilter ),
oidc . TestManagedGroup ( t , conn , authMethod , oidc . TestFakeManagedGroupFilter ),
oidc . TestManagedGroup ( t , conn , authMethod , oidc . TestFakeManagedGroupFilter ),
}
2020-07-10 11:21:11 -07:00
2020-07-10 17:42:47 -07:00
addCases := [] struct {
2021-06-04 09:44:57 -05:00
name string
setup func ( * iam . Role )
addUsers [] string
addGroups [] string
addManagedGroups [] string
resultUsers [] string
resultGroups [] string
resultManagedGroups [] string
wantErr bool
2020-07-10 17:42:47 -07:00
}{
{
name : "Add user on empty role" ,
setup : func ( r * iam . Role ) {},
addUsers : [] string { users [ 1 ]. GetPublicId ()},
resultUsers : [] string { users [ 1 ]. GetPublicId ()},
},
{
name : "Add user on populated role" ,
setup : func ( r * iam . Role ) {
iam . TestUserRole ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
},
addUsers : [] string { users [ 1 ]. GetPublicId ()},
resultUsers : [] string { users [ 0 ]. GetPublicId (), users [ 1 ]. GetPublicId ()},
},
{
name : "Add empty on populated role" ,
setup : func ( r * iam . Role ) {
iam . TestUserRole ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
iam . TestUserRole ( t , conn , r . GetPublicId (), users [ 1 ]. GetPublicId ())
},
wantErr : true ,
},
{
name : "Add group on empty role" ,
setup : func ( r * iam . Role ) {},
addGroups : [] string { groups [ 1 ]. GetPublicId ()},
resultGroups : [] string { groups [ 1 ]. GetPublicId ()},
},
{
name : "Add group on populated role" ,
setup : func ( r * iam . Role ) {
iam . TestGroupRole ( t , conn , r . GetPublicId (), groups [ 0 ]. GetPublicId ())
},
addGroups : [] string { groups [ 1 ]. GetPublicId ()},
resultGroups : [] string { groups [ 0 ]. GetPublicId (), groups [ 1 ]. GetPublicId ()},
},
2020-10-02 16:45:32 -07:00
{
name : "Add duplicate group on populated role" ,
setup : func ( r * iam . Role ) {
iam . TestGroupRole ( t , conn , r . GetPublicId (), groups [ 0 ]. GetPublicId ())
},
addGroups : [] string { groups [ 1 ]. GetPublicId (), groups [ 1 ]. GetPublicId ()},
resultGroups : [] string { groups [ 0 ]. GetPublicId (), groups [ 1 ]. GetPublicId ()},
},
2021-06-04 09:44:57 -05:00
{
name : "Add managed group on empty role" ,
setup : func ( r * iam . Role ) {},
addManagedGroups : [] string { managedGroups [ 1 ]. GetPublicId ()},
resultManagedGroups : [] string { managedGroups [ 1 ]. GetPublicId ()},
},
{
name : "Add managed group on populated role" ,
setup : func ( r * iam . Role ) {
iam . TestManagedGroupRole ( t , conn , r . GetPublicId (), managedGroups [ 0 ]. GetPublicId ())
},
addManagedGroups : [] string { managedGroups [ 1 ]. GetPublicId ()},
resultManagedGroups : [] string { managedGroups [ 0 ]. GetPublicId (), managedGroups [ 1 ]. GetPublicId ()},
},
{
name : "Add duplicate managed group on populated role" ,
setup : func ( r * iam . Role ) {
iam . TestManagedGroupRole ( t , conn , r . GetPublicId (), managedGroups [ 0 ]. GetPublicId ())
},
addManagedGroups : [] string { managedGroups [ 1 ]. GetPublicId (), managedGroups [ 1 ]. GetPublicId ()},
resultManagedGroups : [] string { managedGroups [ 0 ]. GetPublicId (), managedGroups [ 1 ]. GetPublicId ()},
},
2023-06-26 17:05:54 -04:00
{
name : "Add ldap managed group on populated role" ,
setup : func ( r * iam . Role ) {
iam . TestManagedGroupRole ( t , conn , r . GetPublicId (), managedGroups [ 0 ]. GetPublicId ())
},
addManagedGroups : [] string { ldapManagedGroup . GetPublicId ()},
resultManagedGroups : [] string { managedGroups [ 0 ]. GetPublicId (), ldapManagedGroup . GetPublicId ()},
},
2020-08-20 13:34:03 -04:00
{
name : "Add invalid u_recovery on role" ,
setup : func ( r * iam . Role ) {},
2022-10-28 15:52:06 -04:00
addUsers : [] string { globals . RecoveryUserId },
2020-08-20 13:34:03 -04:00
wantErr : true ,
},
2020-07-10 17:42:47 -07:00
}
2020-07-10 11:21:11 -07:00
2020-07-10 17:42:47 -07:00
for _ , tc := range addCases {
for _ , scope := range [] * iam . Scope { o , p } {
t . Run ( tc . name + "_" + scope . GetType (), func ( t * testing . T ) {
role := iam . TestRole ( t , conn , scope . GetPublicId ())
tc . setup ( role )
req := & pbs . AddRolePrincipalsRequest {
2020-09-04 14:48:11 -07:00
Id : role . GetPublicId (),
2020-08-18 17:38:38 -07:00
Version : role . GetVersion (),
2021-06-04 09:44:57 -05:00
PrincipalIds : append ( tc . addUsers , append ( tc . addGroups , tc . addManagedGroups ... ) ... ),
2020-07-10 17:42:47 -07:00
}
2021-03-25 03:15:43 -04:00
got , err := s . AddRolePrincipals ( auth . DisabledAuthTestContext ( repoFn , o . GetPublicId ()), req )
2020-07-10 17:42:47 -07:00
if tc . wantErr {
assert . Error ( t , err )
return
}
s , ok := status . FromError ( err )
2021-06-04 09:44:57 -05:00
require . True ( t , ok , fmt . Sprintf ( "Could not run FromError; input was %s" , pretty . Sprint ( err )))
2020-07-10 17:42:47 -07:00
require . NoError ( t , err , "Got error: %v" , s )
2021-06-04 09:44:57 -05:00
assert . True ( t , equalPrincipals ( got . GetItem (), append ( tc . resultUsers , append ( tc . resultGroups , tc . resultManagedGroups ... ) ... )))
2020-07-10 17:42:47 -07:00
})
}
}
2020-07-10 11:21:11 -07:00
2020-07-10 17:42:47 -07:00
role := iam . TestRole ( t , conn , p . GetPublicId ())
2020-07-10 11:21:11 -07:00
2020-07-10 17:42:47 -07:00
failCases := [] struct {
2020-09-23 08:10:27 -07:00
name string
req * pbs . AddRolePrincipalsRequest
err error
2020-07-10 11:21:11 -07:00
}{
{
2020-07-10 17:42:47 -07:00
name : "Bad Role Id" ,
2020-07-10 11:21:11 -07:00
req : & pbs . AddRolePrincipalsRequest {
2020-09-04 14:48:11 -07:00
Id : "bad id" ,
2020-08-07 12:55:02 -04:00
Version : role . GetVersion (),
2020-07-10 11:21:11 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-07-10 11:21:11 -07:00
},
2020-10-02 16:45:32 -07:00
{
name : "Bad Principal Id" ,
req : & pbs . AddRolePrincipalsRequest {
2020-10-06 13:17:28 -04:00
Id : role . GetPublicId (),
Version : role . GetVersion (),
2020-10-02 16:45:32 -07:00
PrincipalIds : [] string { "invalid" },
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "u_recovery Id" ,
req : & pbs . AddRolePrincipalsRequest {
2020-10-06 13:17:28 -04:00
Id : role . GetPublicId (),
Version : role . GetVersion (),
2022-10-28 15:52:06 -04:00
PrincipalIds : [] string { globals . RecoveryUserId },
2020-10-02 16:45:32 -07:00
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
2020-07-10 17:42:47 -07:00
}
for _ , tc := range failCases {
t . Run ( tc . name , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2021-03-25 03:15:43 -04:00
_ , gErr := s . AddRolePrincipals ( auth . DisabledAuthTestContext ( repoFn , p . GetPublicId ()), tc . req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "AddRolePrincipals(%+v) got error %v, wanted %v" , tc . req , gErr , tc . err )
}
2020-07-10 17:42:47 -07:00
})
}
}
func TestSetPrincipal ( t * testing . T ) {
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-07-10 17:42:47 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-07-10 17:42:47 -07:00
}
2023-12-15 11:49:59 -08:00
s , err := roles . NewService ( context . Background (), repoFn , 1000 )
2020-07-10 17:42:47 -07:00
require . NoError ( t , err , "Error when getting new role service." )
2020-08-19 16:47:18 -04:00
o , p := iam . TestScopes ( t , iamRepo )
2021-06-04 09:44:57 -05:00
ctx := context . Background ()
kmsCache := kms . TestKms ( t , conn , wrap )
databaseWrapper , err := kmsCache . GetWrapper ( ctx , o . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
authMethod := oidc . TestAuthMethod (
t , conn , databaseWrapper , o . GetPublicId (), oidc . ActivePrivateState ,
"alice-rp" , "fido" ,
oidc . WithSigningAlgs ( oidc . RS256 ),
oidc . WithIssuer ( oidc . TestConvertToUrls ( t , "https://www.alice.com" )[ 0 ]),
oidc . WithApiUrl ( oidc . TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]),
)
2023-06-27 12:13:13 -04:00
ldapAuthMethod := ldap . TestAuthMethod ( t , conn , databaseWrapper , o . PublicId , [] string { "ldaps://ldap1" })
ldapManagedGroup := ldap . TestManagedGroup ( t , conn , ldapAuthMethod , [] string { "admin" })
2020-07-10 17:42:47 -07:00
users := [] * iam . User {
2020-08-19 16:47:18 -04:00
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
2020-07-10 17:42:47 -07:00
}
groups := [] * iam . Group {
iam . TestGroup ( t , conn , o . GetPublicId ()),
iam . TestGroup ( t , conn , o . GetPublicId ()),
iam . TestGroup ( t , conn , o . GetPublicId ()),
}
2021-06-04 09:44:57 -05:00
managedGroups := [] * oidc . ManagedGroup {
oidc . TestManagedGroup ( t , conn , authMethod , oidc . TestFakeManagedGroupFilter ),
oidc . TestManagedGroup ( t , conn , authMethod , oidc . TestFakeManagedGroupFilter ),
oidc . TestManagedGroup ( t , conn , authMethod , oidc . TestFakeManagedGroupFilter ),
}
2020-07-10 17:42:47 -07:00
setCases := [] struct {
2021-06-04 09:44:57 -05:00
name string
setup func ( * iam . Role )
setUsers [] string
setGroups [] string
setManagedGroups [] string
resultUsers [] string
resultGroups [] string
resultManagedGroups [] string
wantErr bool
2020-07-10 17:42:47 -07:00
}{
2020-07-10 11:21:11 -07:00
{
2020-07-10 17:42:47 -07:00
name : "Set user on empty role" ,
setup : func ( r * iam . Role ) {},
setUsers : [] string { users [ 1 ]. GetPublicId ()},
resultUsers : [] string { users [ 1 ]. GetPublicId ()},
2020-07-10 11:21:11 -07:00
},
{
2020-07-10 17:42:47 -07:00
name : "Set user on populated role" ,
setup : func ( r * iam . Role ) {
iam . TestUserRole ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
2020-07-10 11:21:11 -07:00
},
2020-07-10 17:42:47 -07:00
setUsers : [] string { users [ 1 ]. GetPublicId ()},
resultUsers : [] string { users [ 1 ]. GetPublicId ()},
2020-07-10 11:21:11 -07:00
},
2020-10-02 16:45:32 -07:00
{
name : "Set duplicate user on populated role" ,
setup : func ( r * iam . Role ) {
iam . TestUserRole ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
},
setUsers : [] string { users [ 1 ]. GetPublicId (), users [ 1 ]. GetPublicId ()},
resultUsers : [] string { users [ 1 ]. GetPublicId ()},
},
2020-07-10 11:21:11 -07:00
{
2020-07-10 17:42:47 -07:00
name : "Set empty on populated role" ,
setup : func ( r * iam . Role ) {
iam . TestUserRole ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
iam . TestUserRole ( t , conn , r . GetPublicId (), users [ 1 ]. GetPublicId ())
2020-07-10 11:21:11 -07:00
},
2020-07-10 17:42:47 -07:00
setUsers : [] string {},
resultUsers : nil ,
2020-07-10 11:21:11 -07:00
},
{
2020-07-10 17:42:47 -07:00
name : "Set group on empty role" ,
setup : func ( r * iam . Role ) {},
setGroups : [] string { groups [ 1 ]. GetPublicId ()},
resultGroups : [] string { groups [ 1 ]. GetPublicId ()},
2020-07-10 11:21:11 -07:00
},
{
2020-07-10 17:42:47 -07:00
name : "Set group on populated role" ,
setup : func ( r * iam . Role ) {
iam . TestGroupRole ( t , conn , r . GetPublicId (), groups [ 0 ]. GetPublicId ())
2020-07-10 11:21:11 -07:00
},
2020-07-10 17:42:47 -07:00
setGroups : [] string { groups [ 1 ]. GetPublicId ()},
resultGroups : [] string { groups [ 1 ]. GetPublicId ()},
2020-07-10 11:21:11 -07:00
},
2021-06-04 09:44:57 -05:00
{
name : "Set managed group on empty role" ,
setup : func ( r * iam . Role ) {},
setManagedGroups : [] string { managedGroups [ 1 ]. GetPublicId ()},
resultManagedGroups : [] string { managedGroups [ 1 ]. GetPublicId ()},
},
{
name : "Set managed group on populated role" ,
setup : func ( r * iam . Role ) {
iam . TestManagedGroupRole ( t , conn , r . GetPublicId (), managedGroups [ 0 ]. GetPublicId ())
},
setManagedGroups : [] string { managedGroups [ 1 ]. GetPublicId ()},
resultManagedGroups : [] string { managedGroups [ 1 ]. GetPublicId ()},
},
2023-06-27 12:13:13 -04:00
{
name : "Set LDAP managed group on populated role" ,
setup : func ( r * iam . Role ) {
iam . TestManagedGroupRole ( t , conn , r . GetPublicId (), managedGroups [ 0 ]. GetPublicId ())
},
setManagedGroups : [] string { ldapManagedGroup . GetPublicId ()},
resultManagedGroups : [] string { ldapManagedGroup . GetPublicId ()},
},
2020-08-20 13:34:03 -04:00
{
name : "Set invalid u_recovery on role" ,
setup : func ( r * iam . Role ) {},
2022-10-28 15:52:06 -04:00
setUsers : [] string { globals . RecoveryUserId },
2020-08-20 13:34:03 -04:00
wantErr : true ,
},
2020-07-10 17:42:47 -07:00
}
for _ , tc := range setCases {
for _ , scope := range [] * iam . Scope { o , p } {
t . Run ( tc . name + "_" + scope . GetType (), func ( t * testing . T ) {
role := iam . TestRole ( t , conn , scope . GetPublicId ())
tc . setup ( role )
req := & pbs . SetRolePrincipalsRequest {
2020-09-04 14:48:11 -07:00
Id : role . GetPublicId (),
2020-08-18 17:38:38 -07:00
Version : role . GetVersion (),
2021-06-04 09:44:57 -05:00
PrincipalIds : append ( tc . setUsers , append ( tc . setGroups , tc . setManagedGroups ... ) ... ),
2020-07-10 17:42:47 -07:00
}
2021-03-25 03:15:43 -04:00
got , err := s . SetRolePrincipals ( auth . DisabledAuthTestContext ( repoFn , o . GetPublicId ()), req )
2020-07-10 17:42:47 -07:00
if tc . wantErr {
assert . Error ( t , err )
return
}
s , ok := status . FromError ( err )
2021-06-04 09:44:57 -05:00
require . True ( t , ok , fmt . Sprintf ( "Could not run FromError; input was %s" , pretty . Sprint ( err )))
2020-07-10 17:42:47 -07:00
require . NoError ( t , err , "Got error: %v" , s )
2021-06-04 09:44:57 -05:00
assert . True ( t , equalPrincipals ( got . GetItem (), append ( tc . resultUsers , append ( tc . resultGroups , tc . resultManagedGroups ... ) ... )))
2020-07-10 17:42:47 -07:00
})
}
}
role := iam . TestRole ( t , conn , p . GetPublicId ())
failCases := [] struct {
2020-09-23 08:10:27 -07:00
name string
req * pbs . SetRolePrincipalsRequest
err error
2020-07-10 17:42:47 -07:00
}{
2020-07-10 11:21:11 -07:00
{
name : "Bad Role Id" ,
2020-07-10 17:42:47 -07:00
req : & pbs . SetRolePrincipalsRequest {
2020-09-04 14:48:11 -07:00
Id : "bad id" ,
2020-08-07 12:55:02 -04:00
Version : role . GetVersion (),
2020-07-10 11:21:11 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-07-10 11:21:11 -07:00
},
2020-10-02 16:45:32 -07:00
{
name : "Bad Principal Id" ,
req : & pbs . SetRolePrincipalsRequest {
2020-10-06 13:17:28 -04:00
Id : role . GetPublicId (),
Version : role . GetVersion (),
2020-10-02 16:45:32 -07:00
PrincipalIds : [] string { "invalid" },
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "u_recovery" ,
req : & pbs . SetRolePrincipalsRequest {
2020-10-06 13:17:28 -04:00
Id : role . GetPublicId (),
Version : role . GetVersion (),
2022-10-28 15:52:06 -04:00
PrincipalIds : [] string { globals . RecoveryUserId },
2020-10-02 16:45:32 -07:00
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
2020-07-10 11:21:11 -07:00
}
2020-07-10 17:42:47 -07:00
for _ , tc := range failCases {
2020-07-10 11:21:11 -07:00
t . Run ( tc . name , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2021-03-25 03:15:43 -04:00
_ , gErr := s . SetRolePrincipals ( auth . DisabledAuthTestContext ( repoFn , p . GetPublicId ()), tc . req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "SetRolePrincipals(%+v) got error %v, wanted %v" , tc . req , gErr , tc . err )
}
2020-07-10 11:21:11 -07:00
})
}
}
2020-07-10 17:42:47 -07:00
func TestRemovePrincipal ( t * testing . T ) {
2023-06-06 17:09:08 -04:00
ctx := context . Background ()
2020-07-10 11:21:11 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-07-10 11:21:11 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-07-10 11:21:11 -07:00
}
2023-12-15 11:49:59 -08:00
s , err := roles . NewService ( ctx , repoFn , 0 )
2020-07-10 11:21:11 -07:00
require . NoError ( t , err , "Error when getting new role service." )
2020-08-19 16:47:18 -04:00
o , p := iam . TestScopes ( t , iamRepo )
2021-06-04 09:44:57 -05:00
kmsCache := kms . TestKms ( t , conn , wrap )
databaseWrapper , err := kmsCache . GetWrapper ( ctx , o . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
authMethod := oidc . TestAuthMethod (
t , conn , databaseWrapper , o . GetPublicId (), oidc . ActivePrivateState ,
"alice-rp" , "fido" ,
oidc . WithSigningAlgs ( oidc . RS256 ),
oidc . WithIssuer ( oidc . TestConvertToUrls ( t , "https://www.alice.com" )[ 0 ]),
oidc . WithApiUrl ( oidc . TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]),
)
2023-06-27 12:13:13 -04:00
ldapAuthMethod := ldap . TestAuthMethod ( t , conn , databaseWrapper , o . PublicId , [] string { "ldaps://ldap1" })
ldapManagedGroup := ldap . TestManagedGroup ( t , conn , ldapAuthMethod , [] string { "admin" })
2020-07-10 17:42:47 -07:00
users := [] * iam . User {
2020-08-19 16:47:18 -04:00
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
2020-07-10 17:42:47 -07:00
}
groups := [] * iam . Group {
iam . TestGroup ( t , conn , o . GetPublicId ()),
iam . TestGroup ( t , conn , o . GetPublicId ()),
iam . TestGroup ( t , conn , o . GetPublicId ()),
}
2021-06-04 09:44:57 -05:00
managedGroups := [] * oidc . ManagedGroup {
oidc . TestManagedGroup ( t , conn , authMethod , oidc . TestFakeManagedGroupFilter ),
oidc . TestManagedGroup ( t , conn , authMethod , oidc . TestFakeManagedGroupFilter ),
oidc . TestManagedGroup ( t , conn , authMethod , oidc . TestFakeManagedGroupFilter ),
}
2020-07-10 17:42:47 -07:00
addCases := [] struct {
2021-06-04 09:44:57 -05:00
name string
setup func ( * iam . Role )
removeUsers [] string
removeGroups [] string
removeManagedGroups [] string
resultUsers [] string
resultGroups [] string
resultManagedGroups [] string
wantErr bool
2020-07-10 11:21:11 -07:00
}{
{
2020-07-10 17:42:47 -07:00
name : "Remove user on empty role" ,
setup : func ( r * iam . Role ) {},
removeUsers : [] string { users [ 1 ]. GetPublicId ()},
wantErr : true ,
2020-07-10 11:21:11 -07:00
},
{
2020-07-10 17:42:47 -07:00
name : "Remove 1 of 2 users from role" ,
setup : func ( r * iam . Role ) {
iam . TestUserRole ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
iam . TestUserRole ( t , conn , r . GetPublicId (), users [ 1 ]. GetPublicId ())
2020-07-10 11:21:11 -07:00
},
2020-07-10 17:42:47 -07:00
removeUsers : [] string { users [ 1 ]. GetPublicId ()},
resultUsers : [] string { users [ 0 ]. GetPublicId ()},
2020-07-10 11:21:11 -07:00
},
2020-10-02 16:45:32 -07:00
{
name : "Remove 1 duplicate user of 2 users from role" ,
setup : func ( r * iam . Role ) {
iam . TestUserRole ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
iam . TestUserRole ( t , conn , r . GetPublicId (), users [ 1 ]. GetPublicId ())
},
removeUsers : [] string { users [ 1 ]. GetPublicId (), users [ 1 ]. GetPublicId ()},
resultUsers : [] string { users [ 0 ]. GetPublicId ()},
},
2020-07-10 11:21:11 -07:00
{
2020-07-10 17:42:47 -07:00
name : "Remove all users from role" ,
setup : func ( r * iam . Role ) {
iam . TestUserRole ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
iam . TestUserRole ( t , conn , r . GetPublicId (), users [ 1 ]. GetPublicId ())
2020-07-10 11:21:11 -07:00
},
2020-07-10 17:42:47 -07:00
removeUsers : [] string { users [ 0 ]. GetPublicId (), users [ 1 ]. GetPublicId ()},
resultUsers : [] string {},
2020-07-10 11:21:11 -07:00
},
{
2020-07-10 17:42:47 -07:00
name : "Remove empty on populated role" ,
setup : func ( r * iam . Role ) {
iam . TestUserRole ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
2020-07-10 11:21:11 -07:00
},
2020-07-10 17:42:47 -07:00
wantErr : true ,
2020-07-10 11:21:11 -07:00
},
{
2020-07-10 17:42:47 -07:00
name : "Remove group on empty role" ,
setup : func ( r * iam . Role ) {},
removeGroups : [] string { groups [ 1 ]. GetPublicId ()},
wantErr : true ,
},
{
name : "Remove 1 of 2 groups from role" ,
setup : func ( r * iam . Role ) {
iam . TestGroupRole ( t , conn , r . GetPublicId (), groups [ 0 ]. GetPublicId ())
iam . TestGroupRole ( t , conn , r . GetPublicId (), groups [ 1 ]. GetPublicId ())
2020-07-10 11:21:11 -07:00
},
2020-07-10 17:42:47 -07:00
removeGroups : [] string { groups [ 1 ]. GetPublicId ()},
resultGroups : [] string { groups [ 0 ]. GetPublicId ()},
2020-07-10 11:21:11 -07:00
},
2020-10-02 16:45:32 -07:00
{
name : "Remove 1 duplicate group of 2 groups from role" ,
setup : func ( r * iam . Role ) {
iam . TestGroupRole ( t , conn , r . GetPublicId (), groups [ 0 ]. GetPublicId ())
iam . TestGroupRole ( t , conn , r . GetPublicId (), groups [ 1 ]. GetPublicId ())
},
removeGroups : [] string { groups [ 1 ]. GetPublicId (), groups [ 1 ]. GetPublicId ()},
resultGroups : [] string { groups [ 0 ]. GetPublicId ()},
},
2020-07-10 11:21:11 -07:00
{
2020-07-10 17:42:47 -07:00
name : "Remove all groups from role" ,
setup : func ( r * iam . Role ) {
iam . TestGroupRole ( t , conn , r . GetPublicId (), groups [ 0 ]. GetPublicId ())
iam . TestGroupRole ( t , conn , r . GetPublicId (), groups [ 1 ]. GetPublicId ())
2020-07-10 11:21:11 -07:00
},
2020-07-10 17:42:47 -07:00
removeGroups : [] string { groups [ 0 ]. GetPublicId (), groups [ 1 ]. GetPublicId ()},
resultGroups : [] string {},
},
2021-06-04 09:44:57 -05:00
{
name : "Remove managed group on empty role" ,
setup : func ( r * iam . Role ) {},
removeGroups : [] string { groups [ 1 ]. GetPublicId ()},
wantErr : true ,
},
{
name : "Remove 1 of 2 managed groups from role" ,
setup : func ( r * iam . Role ) {
iam . TestManagedGroupRole ( t , conn , r . GetPublicId (), managedGroups [ 0 ]. GetPublicId ())
iam . TestManagedGroupRole ( t , conn , r . GetPublicId (), managedGroups [ 1 ]. GetPublicId ())
},
removeManagedGroups : [] string { managedGroups [ 1 ]. GetPublicId ()},
resultManagedGroups : [] string { managedGroups [ 0 ]. GetPublicId ()},
},
{
name : "Remove 1 duplicate managed group of 2 managed groups from role" ,
setup : func ( r * iam . Role ) {
iam . TestManagedGroupRole ( t , conn , r . GetPublicId (), managedGroups [ 0 ]. GetPublicId ())
iam . TestManagedGroupRole ( t , conn , r . GetPublicId (), managedGroups [ 1 ]. GetPublicId ())
},
removeManagedGroups : [] string { managedGroups [ 1 ]. GetPublicId (), managedGroups [ 1 ]. GetPublicId ()},
resultManagedGroups : [] string { managedGroups [ 0 ]. GetPublicId ()},
},
{
name : "Remove all managed groups from role" ,
setup : func ( r * iam . Role ) {
iam . TestManagedGroupRole ( t , conn , r . GetPublicId (), managedGroups [ 0 ]. GetPublicId ())
iam . TestManagedGroupRole ( t , conn , r . GetPublicId (), managedGroups [ 1 ]. GetPublicId ())
},
removeManagedGroups : [] string { managedGroups [ 0 ]. GetPublicId (), managedGroups [ 1 ]. GetPublicId ()},
resultManagedGroups : [] string {},
},
2023-06-27 12:13:13 -04:00
{
name : "Remove LDAP managed groups from role" ,
setup : func ( r * iam . Role ) {
iam . TestManagedGroupRole ( t , conn , r . GetPublicId (), ldapManagedGroup . GetPublicId ())
iam . TestManagedGroupRole ( t , conn , r . GetPublicId (), managedGroups [ 0 ]. GetPublicId ())
},
removeManagedGroups : [] string { ldapManagedGroup . GetPublicId ()},
resultManagedGroups : [] string { managedGroups [ 0 ]. GetPublicId ()},
},
2020-07-10 17:42:47 -07:00
}
for _ , tc := range addCases {
for _ , scope := range [] * iam . Scope { o , p } {
t . Run ( tc . name + "_" + scope . GetType (), func ( t * testing . T ) {
role := iam . TestRole ( t , conn , scope . GetPublicId ())
tc . setup ( role )
req := & pbs . RemoveRolePrincipalsRequest {
2020-09-04 14:48:11 -07:00
Id : role . GetPublicId (),
2020-08-18 17:38:38 -07:00
Version : role . GetVersion (),
2021-06-04 09:44:57 -05:00
PrincipalIds : append ( tc . removeUsers , append ( tc . removeGroups , tc . removeManagedGroups ... ) ... ),
2020-07-10 17:42:47 -07:00
}
2021-03-25 03:15:43 -04:00
got , err := s . RemoveRolePrincipals ( auth . DisabledAuthTestContext ( repoFn , o . GetPublicId ()), req )
2020-07-10 17:42:47 -07:00
if tc . wantErr {
assert . Error ( t , err )
return
}
s , ok := status . FromError ( err )
require . True ( t , ok )
require . NoError ( t , err , "Got error: %v" , s )
2021-06-04 09:44:57 -05:00
assert . True ( t , equalPrincipals ( got . GetItem (), append ( tc . resultUsers , append ( tc . resultGroups , tc . resultManagedGroups ... ) ... )))
2020-07-10 17:42:47 -07:00
})
}
}
role := iam . TestRole ( t , conn , p . GetPublicId ())
failCases := [] struct {
2020-09-23 08:10:27 -07:00
name string
2020-10-02 16:45:32 -07:00
req * pbs . RemoveRolePrincipalsRequest
2020-09-23 08:10:27 -07:00
err error
2020-07-10 17:42:47 -07:00
}{
2020-07-10 11:21:11 -07:00
{
2020-07-10 17:42:47 -07:00
name : "Bad Role Id" ,
2020-10-02 16:45:32 -07:00
req : & pbs . RemoveRolePrincipalsRequest {
2020-09-04 14:48:11 -07:00
Id : "bad id" ,
2020-08-07 12:55:02 -04:00
Version : role . GetVersion (),
2020-07-10 11:21:11 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-07-10 17:42:47 -07:00
},
2020-10-02 16:45:32 -07:00
{
name : "Bad User Id" ,
req : & pbs . RemoveRolePrincipalsRequest {
2020-10-06 13:17:28 -04:00
Id : role . GetPublicId (),
Version : role . GetVersion (),
2020-10-02 16:45:32 -07:00
PrincipalIds : [] string { "g_validgroup" , "invaliduser" },
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "Bad Group Id" ,
req : & pbs . RemoveRolePrincipalsRequest {
2020-10-06 13:17:28 -04:00
Id : role . GetPublicId (),
Version : role . GetVersion (),
2020-10-02 16:45:32 -07:00
PrincipalIds : [] string { "u_validuser" , "invalidgroup" },
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
2020-07-10 17:42:47 -07:00
}
for _ , tc := range failCases {
t . Run ( tc . name , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2021-03-25 03:15:43 -04:00
_ , gErr := s . RemoveRolePrincipals ( auth . DisabledAuthTestContext ( repoFn , p . GetPublicId ()), tc . req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "AddRolePrincipals(%+v) got error %v, wanted %v" , tc . req , gErr , tc . err )
}
2020-07-10 17:42:47 -07:00
})
}
}
2020-07-16 22:18:27 -04:00
func checkEqualGrants ( t * testing . T , expected [] string , got * pb . Role ) {
require , assert := require . New ( t ), assert . New ( t )
require . Equal ( len ( expected ), len ( got . GrantStrings ))
require . Equal ( len ( expected ), len ( got . Grants ))
2024-02-13 10:50:06 -05:00
// sort expected and got to ensure they are in the same order
sort . Strings ( expected )
sort . Slice ( got . GrantStrings , func ( i , j int ) bool {
return got . GrantStrings [ i ] < got . GrantStrings [ j ]
})
2020-07-16 22:18:27 -04:00
for i , v := range expected {
2024-09-17 10:07:43 -04:00
parsed , err := perms . Parse ( context . Background (), perms . GrantTuple { RoleScopeId : "o_abc123" , GrantScopeId : "o_abc123" , Grant : v })
2020-07-16 22:18:27 -04:00
require . NoError ( err )
assert . Equal ( expected [ i ], got . GrantStrings [ i ])
assert . Equal ( expected [ i ], got . Grants [ i ]. GetRaw ())
2020-12-18 13:25:28 -05:00
assert . Equal ( v , got . Grants [ i ]. GetCanonical ())
2020-07-16 22:18:27 -04:00
j := got . Grants [ i ]. GetJson ()
require . NotNil ( j )
assert . Equal ( parsed . Id (), j . GetId ())
2023-06-06 16:13:44 -04:00
assert . Equal ( parsed . Ids (), j . GetIds ())
2020-07-16 22:18:27 -04:00
assert . Equal ( parsed . Type (). String (), j . GetType ())
_ , acts := parsed . Actions ()
assert . Equal ( acts , j . GetActions ())
}
}
2020-07-10 17:42:47 -07:00
func TestAddGrants ( t * testing . T ) {
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-07-10 17:42:47 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-07-10 17:42:47 -07:00
}
2023-12-15 11:49:59 -08:00
s , err := roles . NewService ( context . Background (), repoFn , 1000 )
2020-07-10 17:42:47 -07:00
require . NoError ( t , err , "Error when getting new role service." )
addCases := [] struct {
2022-09-15 09:20:08 -04:00
name string
existing [] string
add [] string
result [] string
wantErr bool
wantErrContains string
2020-07-10 17:42:47 -07:00
}{
{
name : "Add grant on empty role" ,
2023-06-06 16:13:44 -04:00
add : [] string { "ids=*;type=*;actions=delete" },
result : [] string { "ids=*;type=*;actions=delete" },
2020-07-10 17:42:47 -07:00
},
{
name : "Add grant on role with grant" ,
2024-01-17 23:54:49 -08:00
existing : [] string { "ids=u_foo;actions=read" },
2023-06-06 16:13:44 -04:00
add : [] string { "ids=*;type=*;actions=delete" },
2024-01-17 23:54:49 -08:00
result : [] string { "ids=u_foo;actions=read" , "ids=*;type=*;actions=delete" },
2020-07-10 11:21:11 -07:00
},
2020-10-02 16:45:32 -07:00
{
name : "Add duplicate grant on role with grant" ,
2024-01-17 23:54:49 -08:00
existing : [] string { "ids=u_fooaA1;actions=read" },
2023-06-06 16:13:44 -04:00
add : [] string { "ids=*;type=*;actions=delete" , "ids=*;type=*;actions=delete" },
2024-01-17 23:54:49 -08:00
result : [] string { "ids=u_fooaA1;actions=read" , "ids=*;type=*;actions=delete" },
2020-10-02 16:45:32 -07:00
},
2020-07-10 17:42:47 -07:00
{
name : "Add grant matching existing grant" ,
2023-06-06 16:13:44 -04:00
existing : [] string { "ids=u_foo;actions=read" , "ids=*;type=*;actions=delete" },
add : [] string { "ids=*;type=*;actions=delete" },
2020-07-10 17:42:47 -07:00
wantErr : true ,
},
2022-09-15 09:20:08 -04:00
{
2023-06-06 16:13:44 -04:00
name : "Check add-host-sets deprecation" ,
2024-01-17 23:54:49 -08:00
existing : [] string { "ids=u_foo;actions=read" , "ids=*;type=*;actions=delete" },
2023-06-06 16:13:44 -04:00
add : [] string { "ids=*;type=target;actions=add-host-sets" },
2022-09-15 09:20:08 -04:00
wantErr : true ,
wantErrContains : "Use \\\"add-host-sources\\\" instead" ,
},
2023-06-06 16:13:44 -04:00
{
name : "Check id field deprecation" ,
2024-01-25 10:27:22 -08:00
existing : [] string { "id=u_fooaA1;actions=read" },
add : [] string { "id=*;type=*;actions=delete" },
result : [] string { "id=u_fooaA1;actions=read" , "id=*;type=*;actions=delete" },
2023-06-06 16:13:44 -04:00
wantErr : func () bool {
return ! version . SupportsFeature ( version . Binary , version . SupportIdInGrants )
}(),
},
2020-07-10 17:42:47 -07:00
}
for _ , tc := range addCases {
2020-08-19 16:47:18 -04:00
o , p := iam . TestScopes ( t , iamRepo )
2020-07-10 17:42:47 -07:00
for _ , scope := range [] * iam . Scope { o , p } {
t . Run ( tc . name + "_" + scope . Type , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2020-07-10 17:42:47 -07:00
role := iam . TestRole ( t , conn , scope . GetPublicId ())
for _ , e := range tc . existing {
_ = iam . TestRoleGrant ( t , conn , role . GetPublicId (), e )
}
req := & pbs . AddRoleGrantsRequest {
2020-09-04 14:48:11 -07:00
Id : role . GetPublicId (),
2020-08-07 12:55:02 -04:00
Version : role . GetVersion (),
2020-07-10 17:42:47 -07:00
}
2020-07-22 00:14:28 -04:00
scopeId := o . GetPublicId ()
2020-07-10 17:42:47 -07:00
if o != scope {
2020-07-22 00:14:28 -04:00
scopeId = p . GetPublicId ()
2020-07-10 17:42:47 -07:00
}
2020-08-18 17:38:38 -07:00
req . GrantStrings = tc . add
2021-03-25 03:15:43 -04:00
got , err := s . AddRoleGrants ( auth . DisabledAuthTestContext ( repoFn , scopeId ), req )
2020-07-10 17:42:47 -07:00
if tc . wantErr {
assert . Error ( err )
2022-09-15 09:20:08 -04:00
if tc . wantErrContains != "" {
assert . Contains ( err . Error (), tc . wantErrContains )
}
2020-07-10 17:42:47 -07:00
return
}
2020-09-23 08:10:27 -07:00
require . NoError ( err )
2020-07-16 22:18:27 -04:00
checkEqualGrants ( t , tc . result , got . GetItem ())
2020-07-10 17:42:47 -07:00
})
}
}
2020-08-19 16:47:18 -04:00
_ , p := iam . TestScopes ( t , iamRepo )
2020-07-10 17:42:47 -07:00
role := iam . TestRole ( t , conn , p . GetPublicId ())
failCases := [] struct {
2020-09-23 08:10:27 -07:00
name string
req * pbs . AddRoleGrantsRequest
err error
2020-07-10 17:42:47 -07:00
}{
2020-09-25 13:41:20 -07:00
{
name : "Bad Version" ,
req : & pbs . AddRoleGrantsRequest {
Id : role . GetPublicId (),
2023-06-06 16:13:44 -04:00
GrantStrings : [] string { "ids=*;type=*;actions=create" },
2020-09-25 13:41:20 -07:00
Version : role . GetVersion () + 2 ,
},
err : handlers . ApiErrorWithCode ( codes . Internal ),
},
2020-07-10 11:21:11 -07:00
{
name : "Bad Role Id" ,
2020-07-10 17:42:47 -07:00
req : & pbs . AddRoleGrantsRequest {
2020-09-04 14:48:11 -07:00
Id : "bad id" ,
2023-06-06 16:13:44 -04:00
GrantStrings : [] string { "ids=*;type=*;actions=create" },
2020-08-18 17:38:38 -07:00
Version : role . GetVersion (),
2020-07-10 11:21:11 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-07-10 11:21:11 -07:00
},
2020-10-02 16:45:32 -07:00
{
name : "Unparseable Grant" ,
req : & pbs . AddRoleGrantsRequest {
Id : role . GetPublicId (),
2023-06-06 16:13:44 -04:00
GrantStrings : [] string { "ids=*;type=*;actions=create" , "unparseable" },
2020-10-02 16:45:32 -07:00
Version : role . GetVersion (),
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "Empty Grant" ,
req : & pbs . AddRoleGrantsRequest {
Id : role . GetPublicId (),
2023-06-06 16:13:44 -04:00
GrantStrings : [] string { "ids=*;type=*;actions=create" , "" },
2020-10-02 16:45:32 -07:00
Version : role . GetVersion (),
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
2020-07-10 11:21:11 -07:00
}
2020-07-10 17:42:47 -07:00
for _ , tc := range failCases {
2020-07-10 11:21:11 -07:00
t . Run ( tc . name , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2021-03-25 03:15:43 -04:00
_ , gErr := s . AddRoleGrants ( auth . DisabledAuthTestContext ( repoFn , p . GetPublicId ()), tc . req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "AddRoleGrants(%+v) got error %#v, wanted %#v" , tc . req , gErr , tc . err )
}
2020-07-10 11:21:11 -07:00
})
}
}
2020-07-10 17:42:47 -07:00
func TestSetGrants ( t * testing . T ) {
2020-07-10 11:21:11 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-07-10 11:21:11 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-07-10 11:21:11 -07:00
}
2023-12-15 11:49:59 -08:00
s , err := roles . NewService ( context . Background (), repoFn , 1000 )
2020-07-10 11:21:11 -07:00
require . NoError ( t , err , "Error when getting new role service." )
2020-07-10 17:42:47 -07:00
setCases := [] struct {
2022-09-15 09:20:08 -04:00
name string
existing [] string
set [] string
result [] string
wantErr bool
wantErrContains string
2020-07-10 17:42:47 -07:00
}{
{
name : "Set grant on empty role" ,
2023-06-06 16:13:44 -04:00
set : [] string { "ids=*;type=*;actions=delete" },
result : [] string { "ids=*;type=*;actions=delete" },
2020-07-10 17:42:47 -07:00
},
{
name : "Set grant on role with grant" ,
2024-01-17 23:54:49 -08:00
existing : [] string { "ids=u_foo;actions=read" },
2023-06-06 16:13:44 -04:00
set : [] string { "ids=*;type=*;actions=delete" },
result : [] string { "ids=*;type=*;actions=delete" },
2020-07-10 17:42:47 -07:00
},
{
name : "Set grant matching existing grant" ,
2024-01-17 23:54:49 -08:00
existing : [] string { "ids=u_foo;actions=read" , "ids=*;type=*;actions=delete" },
2023-06-06 16:13:44 -04:00
set : [] string { "ids=*;type=*;actions=delete" },
result : [] string { "ids=*;type=*;actions=delete" },
2020-07-10 17:42:47 -07:00
},
{
2020-10-02 16:45:32 -07:00
name : "Set duplicate grant matching existing grant" ,
2024-01-17 23:54:49 -08:00
existing : [] string { "ids=u_foo;actions=read" , "ids=*;type=*;actions=delete" },
2023-06-06 16:13:44 -04:00
set : [] string { "ids=*;type=*;actions=delete" , "ids=*;type=*;actions=delete" },
result : [] string { "ids=*;type=*;actions=delete" },
2020-10-02 16:45:32 -07:00
},
{
name : "Set empty on role" ,
2024-01-17 23:54:49 -08:00
existing : [] string { "ids=hcst_foo;type=*;actions=read" , "ids=*;type=*;actions=delete" },
2020-07-10 17:42:47 -07:00
set : nil ,
result : nil ,
},
2022-09-15 09:20:08 -04:00
{
2023-06-06 16:13:44 -04:00
name : "Check add-host-sets deprecation" ,
2024-01-17 23:54:49 -08:00
existing : [] string { "ids=u_foo;actions=read" , "ids=*;type=*;actions=delete" },
2023-06-06 16:13:44 -04:00
set : [] string { "ids=*;type=target;actions=add-host-sets" },
2022-09-15 09:20:08 -04:00
wantErr : true ,
wantErrContains : "Use \\\"add-host-sources\\\" instead" ,
},
2023-06-06 16:13:44 -04:00
{
name : "Check id field deprecation" ,
2024-01-25 10:27:22 -08:00
existing : [] string { "id=u_fooaA1;actions=read" },
set : [] string { "id=*;type=*;actions=delete" },
result : [] string { "id=*;type=*;actions=delete" },
2023-06-06 16:13:44 -04:00
wantErr : func () bool {
return ! version . SupportsFeature ( version . Binary , version . SupportIdInGrants )
}(),
},
2020-07-10 17:42:47 -07:00
}
for _ , tc := range setCases {
2020-08-19 16:47:18 -04:00
o , p := iam . TestScopes ( t , iamRepo )
2020-07-10 17:42:47 -07:00
for _ , scope := range [] * iam . Scope { o , p } {
t . Run ( tc . name + "_" + scope . Type , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2020-07-10 17:42:47 -07:00
role := iam . TestRole ( t , conn , scope . GetPublicId ())
for _ , e := range tc . existing {
_ = iam . TestRoleGrant ( t , conn , role . GetPublicId (), e )
}
req := & pbs . SetRoleGrantsRequest {
2020-09-04 14:48:11 -07:00
Id : role . GetPublicId (),
2020-08-07 12:55:02 -04:00
Version : role . GetVersion (),
2020-07-10 17:42:47 -07:00
}
2020-07-22 00:14:28 -04:00
scopeId := o . GetPublicId ()
2020-07-10 17:42:47 -07:00
if o != scope {
2020-07-22 00:14:28 -04:00
scopeId = p . GetPublicId ()
2020-07-10 17:42:47 -07:00
}
2020-08-18 17:38:38 -07:00
req . GrantStrings = tc . set
2021-03-25 03:15:43 -04:00
got , err := s . SetRoleGrants ( auth . DisabledAuthTestContext ( repoFn , scopeId ), req )
2020-07-10 17:42:47 -07:00
if tc . wantErr {
assert . Error ( err )
2022-09-15 09:20:08 -04:00
if tc . wantErrContains != "" {
assert . Contains ( err . Error (), tc . wantErrContains )
}
2020-07-10 17:42:47 -07:00
return
}
2020-10-02 16:45:32 -07:00
require . NoError ( err , "Got error %v" , err )
2020-07-16 22:18:27 -04:00
checkEqualGrants ( t , tc . result , got . GetItem ())
2020-07-10 17:42:47 -07:00
})
}
}
2020-08-19 16:47:18 -04:00
_ , p := iam . TestScopes ( t , iamRepo )
2020-07-10 17:42:47 -07:00
role := iam . TestRole ( t , conn , p . GetPublicId ())
failCases := [] struct {
2020-09-23 08:10:27 -07:00
name string
req * pbs . SetRoleGrantsRequest
err error
2020-07-10 11:21:11 -07:00
}{
2020-09-25 13:41:20 -07:00
{
name : "Bad Version" ,
req : & pbs . SetRoleGrantsRequest {
Id : role . GetPublicId (),
2023-06-06 16:13:44 -04:00
GrantStrings : [] string { "ids=*;type=*;actions=create" },
2020-09-25 13:41:20 -07:00
Version : role . GetVersion () + 2 ,
},
err : handlers . ApiErrorWithCode ( codes . Internal ),
},
2020-07-10 11:21:11 -07:00
{
2020-07-10 17:42:47 -07:00
name : "Bad Role Id" ,
req : & pbs . SetRoleGrantsRequest {
2020-09-04 14:48:11 -07:00
Id : "bad id" ,
2023-06-06 16:13:44 -04:00
GrantStrings : [] string { "ids=*;type=*;actions=create" },
2020-08-18 17:38:38 -07:00
Version : role . GetVersion (),
2020-07-10 11:21:11 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-07-10 11:21:11 -07:00
},
2020-10-02 16:45:32 -07:00
{
name : "Unparsable grant" ,
req : & pbs . SetRoleGrantsRequest {
Id : role . GetPublicId (),
2023-06-06 16:13:44 -04:00
GrantStrings : [] string { "ids=*;type=*;actions=create" , "unparseable" },
2020-10-02 16:45:32 -07:00
Version : role . GetVersion (),
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
2020-07-10 17:42:47 -07:00
}
for _ , tc := range failCases {
t . Run ( tc . name , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2021-03-25 03:15:43 -04:00
_ , gErr := s . SetRoleGrants ( auth . DisabledAuthTestContext ( repoFn , p . GetPublicId ()), tc . req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "SetRoleGrants(%+v) got error %v, wanted %v" , tc . req , gErr , tc . err )
}
2020-07-10 17:42:47 -07:00
})
}
}
func TestRemoveGrants ( t * testing . T ) {
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-07-10 17:42:47 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-07-10 17:42:47 -07:00
}
2023-12-15 11:49:59 -08:00
s , err := roles . NewService ( context . Background (), repoFn , 1000 )
2020-07-10 17:42:47 -07:00
require . NoError ( t , err , "Error when getting new role service." )
removeCases := [] struct {
name string
existing [] string
remove [] string
result [] string
wantErr bool
}{
2020-07-10 11:21:11 -07:00
{
2020-07-10 17:42:47 -07:00
name : "Remove all" ,
2024-01-17 23:54:49 -08:00
existing : [] string { "ids=hcst_1;type=*;actions=read" },
remove : [] string { "ids=hcst_1;type=*;actions=read" },
2020-07-10 11:21:11 -07:00
},
{
2020-07-10 17:42:47 -07:00
name : "Remove partial" ,
2024-01-17 23:54:49 -08:00
existing : [] string { "ids=hcst_1;type=*;actions=read" , "ids=hcst_2;type=*;actions=delete" },
remove : [] string { "ids=hcst_1;type=*;actions=read" },
result : [] string { "ids=hcst_2;type=*;actions=delete" },
2020-10-02 16:45:32 -07:00
},
{
name : "Remove duplicate" ,
2024-01-17 23:54:49 -08:00
existing : [] string { "ids=hcst_1;type=*;actions=read" , "ids=hcst_2;type=*;actions=delete" },
remove : [] string { "ids=hcst_1;type=*;actions=read" , "ids=hcst_1;type=*;actions=read" },
result : [] string { "ids=hcst_2;type=*;actions=delete" },
2020-07-10 11:21:11 -07:00
},
{
2024-02-16 08:30:16 -05:00
name : "Remove non existent" ,
2024-01-17 23:54:49 -08:00
existing : [] string { "ids=hcst_2;type=*;actions=delete" },
remove : [] string { "ids=hcst_1;type=*;actions=read" },
result : [] string { "ids=hcst_2;type=*;actions=delete" },
2020-07-10 11:21:11 -07:00
},
2020-07-10 17:42:47 -07:00
{
name : "Remove from empty role" ,
existing : [] string {},
2024-01-17 23:54:49 -08:00
remove : [] string { "ids=hcst_1;type=*;actions=read" },
2020-07-10 17:42:47 -07:00
result : nil ,
},
}
for _ , tc := range removeCases {
2020-08-19 16:47:18 -04:00
o , p := iam . TestScopes ( t , iamRepo )
2020-07-10 17:42:47 -07:00
for _ , scope := range [] * iam . Scope { o , p } {
t . Run ( tc . name + "_" + scope . Type , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2020-07-10 17:42:47 -07:00
role := iam . TestRole ( t , conn , scope . GetPublicId ())
for _ , e := range tc . existing {
_ = iam . TestRoleGrant ( t , conn , role . GetPublicId (), e )
}
req := & pbs . RemoveRoleGrantsRequest {
2020-09-04 14:48:11 -07:00
Id : role . GetPublicId (),
2020-08-07 12:55:02 -04:00
Version : role . GetVersion (),
2020-07-10 17:42:47 -07:00
}
2020-07-22 00:14:28 -04:00
scopeId := o . GetPublicId ()
2020-07-10 17:42:47 -07:00
if o != scope {
2020-07-22 00:14:28 -04:00
scopeId = p . GetPublicId ()
2020-07-10 17:42:47 -07:00
}
2020-08-18 17:38:38 -07:00
req . GrantStrings = tc . remove
2021-03-25 03:15:43 -04:00
got , err := s . RemoveRoleGrants ( auth . DisabledAuthTestContext ( repoFn , scopeId ), req )
2020-07-10 17:42:47 -07:00
if tc . wantErr {
assert . Error ( err )
return
}
s , ok := status . FromError ( err )
assert . True ( ok )
2020-09-23 08:10:27 -07:00
require . NoError ( err , "Got error %v" , s )
2020-07-16 22:18:27 -04:00
checkEqualGrants ( t , tc . result , got . GetItem ())
2020-07-10 17:42:47 -07:00
})
}
}
2020-08-19 16:47:18 -04:00
_ , p := iam . TestScopes ( t , iamRepo )
2020-07-10 17:42:47 -07:00
role := iam . TestRole ( t , conn , p . GetPublicId ())
failCases := [] struct {
name string
req * pbs . RemoveRoleGrantsRequest
2020-09-23 08:10:27 -07:00
err error
2020-07-10 17:42:47 -07:00
}{
2020-09-25 13:41:20 -07:00
{
name : "Bad Version" ,
req : & pbs . RemoveRoleGrantsRequest {
Id : role . GetPublicId (),
2024-01-17 23:54:49 -08:00
GrantStrings : [] string { "ids=hcst_2;type=*;actions=create" },
2020-09-25 13:41:20 -07:00
Version : role . GetVersion () + 2 ,
},
err : handlers . ApiErrorWithCode ( codes . Internal ),
},
2020-07-10 11:21:11 -07:00
{
name : "Bad Role Id" ,
2020-07-10 17:42:47 -07:00
req : & pbs . RemoveRoleGrantsRequest {
2020-09-04 14:48:11 -07:00
Id : "bad id" ,
2024-01-17 23:54:49 -08:00
GrantStrings : [] string { "ids=*;type=*;actions=create" },
2020-10-02 16:45:32 -07:00
Version : role . GetVersion (),
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "Empty Grant" ,
req : & pbs . RemoveRoleGrantsRequest {
Id : role . GetPublicId (),
2024-01-17 23:54:49 -08:00
GrantStrings : [] string { "ids=*;type=*;actions=create" , "" },
2020-10-02 16:45:32 -07:00
Version : role . GetVersion (),
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "Unparseable Grant" ,
req : & pbs . RemoveRoleGrantsRequest {
Id : role . GetPublicId (),
2024-01-17 23:54:49 -08:00
GrantStrings : [] string { "ids=*;type=*;actions=create" , ";unparsable=2" },
2020-08-18 17:38:38 -07:00
Version : role . GetVersion (),
2020-07-10 11:21:11 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-07-10 11:21:11 -07:00
},
}
2020-07-10 17:42:47 -07:00
for _ , tc := range failCases {
2020-07-10 11:21:11 -07:00
t . Run ( tc . name , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2021-03-25 03:15:43 -04:00
_ , gErr := s . RemoveRoleGrants ( auth . DisabledAuthTestContext ( repoFn , p . GetPublicId ()), tc . req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "RemoveRoleGrants(%+v) got error %v, wanted %v" , tc . req , gErr , tc . err )
}
2020-07-10 11:21:11 -07:00
})
}
}
2024-01-23 14:33:09 -05:00
func TestAddGrantScopes ( t * testing . T ) {
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
iamRepo := iam . TestRepo ( t , conn , wrap )
repoFn := func () ( * iam . Repository , error ) {
return iamRepo , nil
}
s , err := roles . NewService ( context . Background (), repoFn , 1000 )
require . NoError ( t , err , "Error when getting new role service." )
o , p := iam . TestScopes ( t , iamRepo )
o2 , p2 := iam . TestScopes ( t , iamRepo )
addCases := [] struct {
name string
scopeId string
existing [] string
add [] string
result [] string
wantErr bool
wantErrContains string
}{
{
name : "Add grant scopes on empty role - global" ,
scopeId : scope . Global . String (),
add : [] string { "this" , "descendants" },
result : [] string { "this" , "descendants" },
},
{
name : "Add grant scopes on role with grant scopes - global" ,
scopeId : scope . Global . String (),
existing : [] string { "global" , o . PublicId },
add : [] string { "children" , p . PublicId },
result : [] string { "global" , o . PublicId , p . PublicId , "children" },
},
{
name : "Add duplicate grant on role with grant scopes - global" ,
scopeId : scope . Global . String (),
existing : [] string { "this" },
add : [] string { "children" , "children" },
result : [] string { "this" , "children" },
},
{
name : "Add other org/proj scopes - global" ,
scopeId : scope . Global . String (),
existing : [] string { "this" },
add : [] string { o2 . PublicId , p2 . PublicId },
result : [] string { "this" , o2 . PublicId , p2 . PublicId },
},
{
name : "Add grant scope matching existing grant scopes - global" ,
scopeId : scope . Global . String (),
existing : [] string { "this" },
add : [] string { "this" , "children" },
wantErr : true ,
},
{
name : "Add invalid grant scope - global" ,
scopeId : scope . Global . String (),
existing : [] string { "this" },
add : [] string { "p_foobar1234" , "children" },
wantErr : true ,
},
{
name : "Add this to scope grant scope - global" ,
scopeId : scope . Global . String (),
existing : [] string { scope . Global . String ()},
add : [] string { "this" },
wantErr : true ,
},
{
name : "Add scope to this grant scope - global" ,
scopeId : scope . Global . String (),
existing : [] string { "this" },
add : [] string { scope . Global . String ()},
wantErr : true ,
},
{
name : "Add children when descendants exists - global" ,
scopeId : scope . Global . String (),
existing : [] string { "descendants" },
add : [] string { "children" },
wantErr : true ,
},
{
name : "Add descendants when children exists - global" ,
scopeId : scope . Global . String (),
existing : [] string { "children" },
add : [] string { "descendants" },
wantErr : true ,
},
{
name : "Add grant scopes on empty role - org" ,
scopeId : o . PublicId ,
add : [] string { "this" , "children" },
result : [] string { "this" , "children" },
},
{
name : "Add grant scopes on role with grant scopes - org" ,
scopeId : o . PublicId ,
existing : [] string { o . PublicId , p . PublicId },
add : [] string { "children" },
result : [] string { o . PublicId , p . PublicId , "children" },
},
{
name : "Add duplicate grant on role with grant scopes - org" ,
scopeId : o . PublicId ,
existing : [] string { "this" },
add : [] string { "children" , "children" },
result : [] string { "this" , "children" },
},
{
name : "Add grant scope matching existing grant scopes - org" ,
scopeId : o . PublicId ,
existing : [] string { "this" },
add : [] string { "this" , "children" },
wantErr : true ,
},
{
name : "Add invalid grant scope - org" ,
scopeId : o . PublicId ,
existing : [] string { "this" },
add : [] string { "p_foobar1234" , "children" },
wantErr : true ,
},
{
name : "Add invalid grant scope - org - descendants" ,
scopeId : o . PublicId ,
existing : [] string { "this" },
add : [] string { "descendants" , "children" },
wantErr : true ,
},
{
name : "Add this to scope grant scope - org" ,
scopeId : o . PublicId ,
existing : [] string { o . PublicId },
add : [] string { "this" },
wantErr : true ,
},
{
name : "Add scope to this grant scope - org" ,
scopeId : o . PublicId ,
existing : [] string { "this" },
add : [] string { o . PublicId },
wantErr : true ,
},
{
name : "Add other org/proj scopes - org" ,
scopeId : o . PublicId ,
existing : [] string { "this" },
add : [] string { p2 . PublicId },
wantErr : true ,
},
{
name : "Add grant scopes on empty role - proj with id" ,
scopeId : p . PublicId ,
add : [] string { p . PublicId },
result : [] string { p . PublicId },
},
{
name : "Add grant scopes on empty role - proj with this" ,
scopeId : p . PublicId ,
add : [] string { "this" },
result : [] string { "this" },
},
{
name : "Add duplicate scopes on empty role - proj" ,
scopeId : p . PublicId ,
add : [] string { "this" , "this" },
result : [] string { "this" },
},
{
name : "Add invalid grant scope - proj" ,
scopeId : p . PublicId ,
existing : [] string { "this" },
add : [] string { "p_foobar1234" },
wantErr : true ,
},
{
name : "Add invalid grant scope - proj - descendants" ,
scopeId : p . PublicId ,
existing : [] string { "this" },
add : [] string { "descendants" },
wantErr : true ,
},
{
name : "Add invalid grant scope - proj - children" ,
scopeId : p . PublicId ,
existing : [] string { "this" },
add : [] string { "children" },
wantErr : true ,
},
{
name : "Add this to scope grant scope - proj" ,
scopeId : p . PublicId ,
existing : [] string { p . PublicId },
add : [] string { "this" },
wantErr : true ,
},
{
name : "Add scope to this grant scope - proj" ,
scopeId : p . PublicId ,
existing : [] string { "this" },
add : [] string { p . PublicId },
wantErr : true ,
},
{
name : "Add other org/proj scopes - proj" ,
scopeId : p . PublicId ,
existing : [] string {},
add : [] string { p2 . PublicId },
wantErr : true ,
},
}
for _ , tc := range addCases {
t . Run ( tc . name , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
role := iam . TestRole ( t , conn , tc . scopeId , iam . WithGrantScopeIds ([] string { "testing-none" }))
for _ , e := range tc . existing {
_ = iam . TestRoleGrantScope ( t , conn , role . GetPublicId (), e )
}
req := & pbs . AddRoleGrantScopesRequest {
Id : role . GetPublicId (),
Version : role . GetVersion (),
}
req . GrantScopeIds = tc . add
got , err := s . AddRoleGrantScopes ( auth . DisabledAuthTestContext ( repoFn , tc . scopeId ), req )
if tc . wantErr {
assert . Error ( err )
if tc . wantErrContains != "" {
assert . Contains ( err . Error (), tc . wantErrContains )
}
return
}
require . NoError ( err )
require . ElementsMatch ( tc . result , got . GetItem (). GetGrantScopeIds ())
})
}
_ , p = iam . TestScopes ( t , iamRepo )
role := iam . TestRole ( t , conn , p . GetPublicId (), iam . WithGrantScopeIds ([] string { "testing-none" }))
failCases := [] struct {
name string
req * pbs . AddRoleGrantScopesRequest
err error
}{
{
name : "Bad Version" ,
req : & pbs . AddRoleGrantScopesRequest {
Id : role . GetPublicId (),
GrantScopeIds : [] string { "this" },
Version : role . GetVersion () + 2 ,
},
err : handlers . ApiErrorWithCode ( codes . Internal ),
},
{
name : "Bad Role Id" ,
req : & pbs . AddRoleGrantScopesRequest {
Id : "bad id" ,
GrantScopeIds : [] string { "this" },
Version : role . GetVersion (),
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "Invalid scope ID" ,
req : & pbs . AddRoleGrantScopesRequest {
Id : role . GetPublicId (),
GrantScopeIds : [] string { "p_foobar1234" },
Version : role . GetVersion (),
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "Empty Grant Scope ID" ,
req : & pbs . AddRoleGrantScopesRequest {
Id : role . GetPublicId (),
GrantScopeIds : [] string { "this" , "" },
Version : role . GetVersion (),
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
}
for _ , tc := range failCases {
t . Run ( tc . name , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
_ , gErr := s . AddRoleGrantScopes ( auth . DisabledAuthTestContext ( repoFn , p . GetPublicId ()), tc . req )
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "AddRoleGrantScopes(%+v) got error %#v, wanted %#v" , tc . req , gErr , tc . err )
}
})
}
}
func TestSetGrantScopes ( t * testing . T ) {
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
iamRepo := iam . TestRepo ( t , conn , wrap )
repoFn := func () ( * iam . Repository , error ) {
return iamRepo , nil
}
s , err := roles . NewService ( context . Background (), repoFn , 1000 )
require . NoError ( t , err , "Error when getting new role service." )
o , p := iam . TestScopes ( t , iamRepo )
o2 , p2 := iam . TestScopes ( t , iamRepo )
setCases := [] struct {
name string
scopeId string
existing [] string
set [] string
result [] string
wantErr bool
wantErrContains string
}{
{
name : "Set grant scopes on empty role - global" ,
scopeId : scope . Global . String (),
set : [] string { "this" , "descendants" },
result : [] string { "this" , "descendants" },
},
{
name : "Set grant scopes on role with grant scopes - global" ,
scopeId : scope . Global . String (),
existing : [] string { "global" , o . PublicId },
set : [] string { "children" , p . PublicId },
result : [] string { "children" , p . PublicId },
},
{
name : "Set duplicate grant on role with grant scopes - global" ,
scopeId : scope . Global . String (),
existing : [] string { "this" },
set : [] string { "children" , "children" },
result : [] string { "children" },
},
{
name : "Set grant scope matching existing grant scopes - global" ,
scopeId : scope . Global . String (),
existing : [] string { "this" },
set : [] string { "this" , "children" },
result : [] string { "this" , "children" },
},
{
name : "Set this to scope grant scope - global" ,
scopeId : scope . Global . String (),
existing : [] string { scope . Global . String ()},
set : [] string { "this" , "children" },
result : [] string { "this" , "children" },
},
{
name : "Set scope to this grant scope - global" ,
scopeId : scope . Global . String (),
existing : [] string { "this" },
set : [] string { scope . Global . String (), "children" },
result : [] string { scope . Global . String (), "children" },
},
{
name : "Set other org/proj scopes - global" ,
scopeId : scope . Global . String (),
existing : [] string { "this" },
set : [] string { "this" , o2 . PublicId , p2 . PublicId },
result : [] string { "this" , o2 . PublicId , p2 . PublicId },
},
{
name : "Set invalid grant scope - global" ,
scopeId : scope . Global . String (),
existing : [] string { "this" },
set : [] string { "p_foobar1234" , "children" },
wantErr : true ,
},
{
name : "Set both on grant scope - global" ,
scopeId : scope . Global . String (),
existing : [] string {},
set : [] string { scope . Global . String (), "children" , "this" },
wantErr : true ,
},
{
name : "Set both grant scope - global" ,
scopeId : scope . Global . String (),
existing : [] string {},
set : [] string { "this" , scope . Global . String (), "children" },
wantErr : true ,
},
{
name : "Set children and descendants - global" ,
scopeId : scope . Global . String (),
existing : [] string {},
set : [] string { "children" , "descendants" },
wantErr : true ,
},
{
name : "Set descendants and children- global" ,
scopeId : scope . Global . String (),
existing : [] string {},
set : [] string { "descendants" , "children" },
wantErr : true ,
},
{
name : "Set grant scopes on empty role - org" ,
scopeId : o . PublicId ,
set : [] string { "this" , "children" },
result : [] string { "this" , "children" },
},
{
name : "Set grant scopes on role with grant scopes - org" ,
scopeId : o . PublicId ,
existing : [] string { o . PublicId , p . PublicId },
set : [] string { "children" },
result : [] string { "children" },
},
{
name : "Set duplicate grant on role with grant scopes - org" ,
scopeId : o . PublicId ,
existing : [] string { "this" },
set : [] string { p . PublicId , "children" , "children" },
result : [] string { p . PublicId , "children" },
},
{
name : "Set grant scope matching existing grant scopes - org" ,
scopeId : o . PublicId ,
existing : [] string { "this" },
set : [] string { "this" , "children" },
result : [] string { "this" , "children" },
},
{
name : "Set this to scope grant scope - org" ,
scopeId : o . PublicId ,
existing : [] string { o . PublicId },
set : [] string { "this" , "children" },
result : [] string { "this" , "children" },
},
{
name : "Set scope to this grant scope - org" ,
scopeId : o . PublicId ,
existing : [] string { "this" },
set : [] string { o . PublicId , "children" },
result : [] string { o . PublicId , "children" },
},
{
name : "Set invalid grant scope - org" ,
scopeId : o . PublicId ,
existing : [] string { "this" },
set : [] string { "p_foobar1234" , "children" },
wantErr : true ,
},
{
name : "Set invalid grant scope - org - descendants" ,
scopeId : o . PublicId ,
existing : [] string { "this" },
set : [] string { "descendants" , "children" },
wantErr : true ,
},
{
name : "Set both on grant scope - org" ,
scopeId : o . PublicId ,
existing : [] string {},
set : [] string { o . PublicId , "children" , "this" },
wantErr : true ,
},
{
name : "Set both grant scope - org" ,
scopeId : o . PublicId ,
existing : [] string {},
set : [] string { "this" , o . PublicId , "children" },
wantErr : true ,
},
{
name : "Set grant scopes on empty role - proj with id" ,
scopeId : p . PublicId ,
set : [] string { p . PublicId },
result : [] string { p . PublicId },
},
{
name : "Set grant scopes on empty role - proj with this" ,
scopeId : p . PublicId ,
set : [] string { "this" },
result : [] string { "this" },
},
{
name : "Set duplicate scopes on empty role - proj" ,
scopeId : p . PublicId ,
set : [] string { "this" , "this" },
result : [] string { "this" },
},
{
name : "Set this to scope grant scope - proj" ,
scopeId : p . PublicId ,
existing : [] string { p . PublicId },
set : [] string { "this" },
result : [] string { "this" },
},
{
name : "Set scope to this grant scope - proj" ,
scopeId : p . PublicId ,
existing : [] string { "this" },
set : [] string { p . PublicId },
result : [] string { p . PublicId },
},
{
name : "Set other org/proj scopes - org" ,
scopeId : o . PublicId ,
existing : [] string { "this" },
set : [] string { "this" , p2 . PublicId },
wantErr : true ,
},
{
name : "Set invalid grant scope - proj" ,
scopeId : p . PublicId ,
existing : [] string { "this" },
set : [] string { "p_foobar1234" },
wantErr : true ,
},
{
name : "Set invalid grant scope - proj - descendants" ,
scopeId : p . PublicId ,
existing : [] string { "this" },
set : [] string { "descendants" },
wantErr : true ,
},
{
name : "Set invalid grant scope - proj - children" ,
scopeId : p . PublicId ,
existing : [] string { "this" },
set : [] string { "children" },
wantErr : true ,
},
{
name : "Set both on grant scope - proj" ,
scopeId : p . PublicId ,
existing : [] string {},
set : [] string { p . PublicId , "this" },
wantErr : true ,
},
{
name : "Set both grant scope - proj" ,
scopeId : p . PublicId ,
existing : [] string {},
set : [] string { "this" , p . PublicId },
wantErr : true ,
},
{
name : "Set other org/proj scopes - proj" ,
scopeId : p . PublicId ,
existing : [] string {},
set : [] string { p2 . PublicId },
wantErr : true ,
},
}
for _ , tc := range setCases {
t . Run ( tc . name , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
role := iam . TestRole ( t , conn , tc . scopeId , iam . WithGrantScopeIds ([] string { "testing-none" }))
for _ , e := range tc . existing {
_ = iam . TestRoleGrantScope ( t , conn , role . GetPublicId (), e )
}
req := & pbs . SetRoleGrantScopesRequest {
Id : role . GetPublicId (),
Version : role . GetVersion (),
}
req . GrantScopeIds = tc . set
got , err := s . SetRoleGrantScopes ( auth . DisabledAuthTestContext ( repoFn , tc . scopeId ), req )
if tc . wantErr {
assert . Error ( err )
if tc . wantErrContains != "" {
assert . Contains ( err . Error (), tc . wantErrContains )
}
return
}
require . NoError ( err )
require . ElementsMatch ( tc . result , got . GetItem (). GetGrantScopeIds ())
})
}
role := iam . TestRole ( t , conn , p . GetPublicId (), iam . WithGrantScopeIds ([] string { "testing-none" }))
failCases := [] struct {
name string
req * pbs . SetRoleGrantScopesRequest
err error
}{
{
name : "Bad Version" ,
req : & pbs . SetRoleGrantScopesRequest {
Id : role . GetPublicId (),
GrantScopeIds : [] string { "this" },
Version : role . GetVersion () + 2 ,
},
err : handlers . ApiErrorWithCode ( codes . Internal ),
},
{
name : "Bad Role Id" ,
req : & pbs . SetRoleGrantScopesRequest {
Id : "bad id" ,
GrantScopeIds : [] string { "this" },
Version : role . GetVersion (),
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "Invalid scope ID" ,
req : & pbs . SetRoleGrantScopesRequest {
Id : role . GetPublicId (),
GrantScopeIds : [] string { "p_foobar1234" },
Version : role . GetVersion (),
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "Empty Grant Scope ID" ,
req : & pbs . SetRoleGrantScopesRequest {
Id : role . GetPublicId (),
GrantScopeIds : [] string { "this" , "" },
Version : role . GetVersion (),
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
}
for _ , tc := range failCases {
t . Run ( tc . name , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
_ , gErr := s . SetRoleGrantScopes ( auth . DisabledAuthTestContext ( repoFn , p . GetPublicId ()), tc . req )
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "SetRoleGrantScopes(%+v) got error %#v, wanted %#v" , tc . req , gErr , tc . err )
}
})
}
}
func TestRemoveGrantScopes ( t * testing . T ) {
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
iamRepo := iam . TestRepo ( t , conn , wrap )
repoFn := func () ( * iam . Repository , error ) {
return iamRepo , nil
}
s , err := roles . NewService ( context . Background (), repoFn , 1000 )
require . NoError ( t , err , "Error when getting new role service." )
o , p := iam . TestScopes ( t , iamRepo )
removeCases := [] struct {
name string
scopeId string
existing [] string
remove [] string
result [] string
wantErr bool
}{
{
name : "Remove all - global" ,
scopeId : scope . Global . String (),
existing : [] string { "this" , "descendants" },
remove : [] string { "this" , "descendants" },
},
{
name : "Remove partial - global" ,
scopeId : scope . Global . String (),
existing : [] string { "this" , o . PublicId , "descendants" , p . PublicId },
remove : [] string { o . PublicId , p . PublicId },
result : [] string { "this" , "descendants" },
},
{
name : "Remove duplicate - global" ,
scopeId : scope . Global . String (),
existing : [] string { "this" , "children" , o . PublicId },
remove : [] string { "children" , o . PublicId , "children" },
result : [] string { "this" },
},
{
2024-02-16 08:30:16 -05:00
name : "Remove non existent - global" ,
2024-01-23 14:33:09 -05:00
scopeId : scope . Global . String (),
existing : [] string { "this" , "descendants" },
remove : [] string { "p_foobar1234" },
result : [] string { "this" , "descendants" },
},
{
name : "Remove from empty role - global" ,
scopeId : scope . Global . String (),
existing : [] string {},
remove : [] string { "this" },
result : nil ,
},
{
name : "Remove all - org" ,
scopeId : o . PublicId ,
existing : [] string { "this" , "children" },
remove : [] string { "this" , "children" },
},
{
name : "Remove partial - org" ,
scopeId : o . PublicId ,
existing : [] string { "children" , o . PublicId , p . PublicId },
remove : [] string { "children" },
result : [] string { o . PublicId , p . PublicId },
},
{
name : "Remove duplicate - org" ,
scopeId : o . PublicId ,
existing : [] string { "this" , p . PublicId , "children" },
remove : [] string { "children" , p . PublicId , "children" },
result : [] string { "this" },
},
{
2024-02-16 08:30:16 -05:00
name : "Remove non existent - org" ,
2024-01-23 14:33:09 -05:00
scopeId : o . PublicId ,
existing : [] string { "this" , "children" },
remove : [] string { "p_foobar1234" },
result : [] string { "this" , "children" },
},
{
name : "Remove from empty role - org" ,
scopeId : o . PublicId ,
existing : [] string {},
remove : [] string { "this" },
result : nil ,
},
{
name : "Remove all - proj" ,
scopeId : p . PublicId ,
existing : [] string { p . PublicId },
remove : [] string { p . PublicId },
},
{
name : "Remove duplicate - proj" ,
scopeId : p . PublicId ,
existing : [] string { "this" },
remove : [] string { "this" , "this" },
result : [] string {},
},
{
2024-02-16 08:30:16 -05:00
name : "Remove non existent - proj" ,
2024-01-23 14:33:09 -05:00
scopeId : p . PublicId ,
existing : [] string { "this" },
remove : [] string { "p_foobar1234" },
result : [] string { "this" },
},
{
name : "Remove from empty role - proj" ,
scopeId : p . PublicId ,
existing : [] string {},
remove : [] string { "this" },
result : nil ,
},
}
for _ , tc := range removeCases {
t . Run ( tc . name + "_" , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
role := iam . TestRole ( t , conn , tc . scopeId , iam . WithGrantScopeIds ([] string { "testing-none" }))
for _ , e := range tc . existing {
_ = iam . TestRoleGrantScope ( t , conn , role . GetPublicId (), e )
}
req := & pbs . RemoveRoleGrantScopesRequest {
Id : role . GetPublicId (),
Version : role . GetVersion (),
}
req . GrantScopeIds = tc . remove
got , err := s . RemoveRoleGrantScopes ( auth . DisabledAuthTestContext ( repoFn , tc . scopeId ), req )
if tc . wantErr {
assert . Error ( err )
return
}
s , ok := status . FromError ( err )
assert . True ( ok )
require . NoError ( err , "Got error %v" , s )
require . ElementsMatch ( tc . result , got . GetItem (). GetGrantScopeIds ())
})
}
role := iam . TestRole ( t , conn , p . GetPublicId (), iam . WithGrantScopeIds ([] string { "testing-none" }))
failCases := [] struct {
name string
req * pbs . RemoveRoleGrantScopesRequest
err error
}{
{
name : "Bad Version" ,
req : & pbs . RemoveRoleGrantScopesRequest {
Id : role . GetPublicId (),
GrantScopeIds : [] string { "this" },
Version : role . GetVersion () + 2 ,
},
err : handlers . ApiErrorWithCode ( codes . Internal ),
},
{
name : "Bad Role Id" ,
req : & pbs . RemoveRoleGrantScopesRequest {
Id : "bad id" ,
GrantScopeIds : [] string { "this" },
Version : role . GetVersion (),
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "Empty Grant Scope ID" ,
req : & pbs . RemoveRoleGrantScopesRequest {
Id : role . GetPublicId (),
GrantScopeIds : [] string { "this" , "" },
Version : role . GetVersion (),
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "Invalid Grant Scope ID" ,
req : & pbs . RemoveRoleGrantScopesRequest {
Id : role . GetPublicId (),
GrantScopeIds : [] string { "r_foobar1234" },
Version : role . GetVersion (),
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
}
for _ , tc := range failCases {
t . Run ( tc . name , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
_ , gErr := s . RemoveRoleGrantScopes ( auth . DisabledAuthTestContext ( repoFn , p . GetPublicId ()), tc . req )
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "RemoveRoleGrantScopes(%+v) got error %v, wanted %v" , tc . req , gErr , tc . err )
}
})
}
}