tests (ldap managed groups): extend tests to include ldap grps for GrantsForUser(...) (#3972)

* chore (managed groups): just a small rename to improve readability

* test (aut/ldap): add a test for user grants based on ldap grp

* tests (role grant): extend TestGrantsForUser(...) to cover ldap grps

* refact (iam.(Repository).GrantsForUser): more readable grantsQuery

Convert existing CTE to use sub-selects for readability
pull/4073/head
Jim 2 years ago committed by GitHub
parent 2e31771be3
commit 798e86cefe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,123 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package ldap
import (
"context"
"testing"
"github.com/hashicorp/boundary/internal/auth/oidc"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TestLdapManagedGroupRoleGrants ensures that user roles that
// include a ldap managed groups principal are properly returned from queries to
// auth_managed_group_member_account and iam repository.GrantsForUser(...)
//
// this test depends on changes made in 65/01_ldap.up.sql to the
// auth_managed_group_member_account view
func TestLdapManagedGroupRoleGrants(t *testing.T) {
t.Parallel()
const (
testGrpName = "testAdminGrp"
testGrpName2 = "testUserGrp"
testLdapUrl = "ldap://test.ldap"
testLoginName = "test-user"
testGrant = "id=*;type=*;actions=*"
testClientId = "alice-rp"
testClientSecret = "fido"
testIssuer = "https://www.alice.com"
testCallbackUrl = "https://www.alice.com/callback"
)
testCtx := context.Background()
testConn, _ := db.TestSetup(t, "postgres")
testRootWrapper := db.TestWrapper(t)
testRw := db.New(testConn)
testKms := kms.TestKms(t, testConn, testRootWrapper)
iamRepo := iam.TestRepo(t, testConn, testRootWrapper)
testOrg, _ := iam.TestScopes(
t,
iamRepo,
iam.WithSkipAdminRoleCreation(true),
iam.WithSkipDefaultRoleCreation(true),
)
testScopeId := testOrg.GetPublicId()
testGlobalDbWrapper, err := testKms.GetWrapper(testCtx, testScopeId, kms.KeyPurposeDatabase)
require.NoError(t, err)
ldapRepo, err := NewRepository(testCtx, testRw, testRw, testKms)
require.NoError(t, err)
testAm := TestAuthMethod(t, testConn, testGlobalDbWrapper, testScopeId, []string{testLdapUrl})
testAcct := TestAccount(t, testConn, testAm, testLoginName, WithMemberOfGroups(testCtx, testGrpName))
testManagedGrp := TestManagedGroup(t, testConn, testAm, []string{testGrpName})
TestManagedGroup(t, testConn, testAm, []string{testGrpName2})
testUser := iam.TestUser(t, iamRepo, testScopeId, iam.WithAccountIds(testAcct.PublicId))
testRole := iam.TestRole(t, testConn, testScopeId)
_ = iam.TestRoleGrant(t, testConn, testRole.GetPublicId(), testGrant)
iam.TestManagedGroupRole(t, testConn, testRole.GetPublicId(), testManagedGrp.GetPublicId())
// check the view to make sure it's correct, before trying the CTE used by
// GrantsForUser(...) which depends on this view
memberAccts, err := ldapRepo.ListManagedGroupMembershipsByMember(testCtx, testAcct.GetPublicId())
require.NoError(t, err)
require.Len(t, memberAccts, 1)
require.Equal(t, testManagedGrp.GetPublicId(), memberAccts[0].GetManagedGroupId())
require.Equal(t, testAcct.GetPublicId(), memberAccts[0].GetMemberId())
t.Log("found managed group member acct: ", memberAccts[0].GetManagedGroupId(), memberAccts[0].GetMemberId())
// okay, let's try the CTE and make sure the user has the grants given via
// the ldap managed group
tuples, err := iamRepo.GrantsForUser(testCtx, testUser.PublicId)
require.NoError(t, err)
// De-dupe role IDs
roleIds := make(map[string]bool, len(tuples))
for _, tuple := range tuples {
roleIds[tuple.RoleId] = true
}
t.Log("looking for role: ", testRole.GetPublicId())
t.Log("found role/grant: ", tuples)
assert.EqualValues(t, map[string]bool{testRole.GetPublicId(): true}, roleIds)
// make sure a user without the appropriate managed group doesn't have grants
testUserWithoutManagedGroupRole := iam.TestUser(t, iamRepo, testScopeId)
tuples, err = iamRepo.GrantsForUser(testCtx, testUserWithoutManagedGroupRole.PublicId)
require.NoError(t, err)
assert.Equal(t, 0, len(tuples))
// okay, let's test a user that has both an oidc managed group and an ldap
// managed group
testOidcAm := oidc.TestAuthMethod(
t, testConn, testGlobalDbWrapper, testScopeId, oidc.ActivePrivateState,
testClientId, testClientSecret,
oidc.WithSigningAlgs(oidc.RS256),
oidc.WithIssuer(oidc.TestConvertToUrls(t, testIssuer)[0]),
oidc.WithApiUrl(oidc.TestConvertToUrls(t, testCallbackUrl)[0]),
)
testOidcAcct := oidc.TestAccount(t, testConn, testOidcAm, "sub")
testOidcManagedGrp := oidc.TestManagedGroup(t, testConn, testOidcAm, oidc.TestFakeManagedGroupFilter)
oidc.TestManagedGroupMember(t, testConn, testOidcManagedGrp.GetPublicId(), testOidcAcct.GetPublicId())
// add the oidc account to our test user....
_, err = iamRepo.AddUserAccounts(testCtx, testUser.GetPublicId(), 2, []string{testOidcAcct.GetPublicId()})
require.NoError(t, err)
testRole2 := iam.TestRole(t, testConn, testScopeId)
_ = iam.TestRoleGrant(t, testConn, testRole2.GetPublicId(), testGrant)
iam.TestManagedGroupRole(t, testConn, testRole2.GetPublicId(), testOidcManagedGrp.GetPublicId())
tuples, err = iamRepo.GrantsForUser(testCtx, testUser.GetPublicId())
require.NoError(t, err)
assert.Equal(t, 2, len(tuples))
t.Log("tuples:", tuples)
assert.Equal(t,
map[string]bool{testRole.GetPublicId(): true, testRole2.GetPublicId(): true},
map[string]bool{tuples[0].RoleId: true, tuples[1].RoleId: true},
)
}

@ -606,11 +606,11 @@ func (s Service) listFromRepo(ctx context.Context, authMethodId string) ([]auth.
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
oidcl, err := ldapRepo.ListManagedGroups(ctx, authMethodId, ldap.WithLimit(ctx, -1))
ldapUl, err := ldapRepo.ListManagedGroups(ctx, authMethodId, ldap.WithLimit(ctx, -1))
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
for _, a := range oidcl {
for _, a := range ldapUl {
outUl = append(outUl, a)
}
}

@ -111,4 +111,69 @@ const (
select * from final
order by action, member_id;
`
grantsQuery = `
with
users (id) as (
select public_id
from iam_user
%s -- anonUser || authUser
),
user_groups (id) as (
select group_id
from iam_group_member_user
where member_id in (select id from users)
),
user_accounts (id) as (
select public_id
from auth_account
where iam_user_id in (select id from users)
),
user_managed_groups (id) as (
select managed_group_id
from auth_managed_group_member_account
where member_id in (select id from user_accounts)
),
managed_group_roles (role_id) as (
select role_id
from iam_managed_group_role
where principal_id in (select id from user_managed_groups)
),
group_roles (role_id) as (
select role_id
from iam_group_role
where principal_id in (select id from user_groups)
),
user_roles (role_id) as (
select role_id
from iam_user_role
where principal_id in (select id from users)
),
user_group_roles (role_id) as (
select role_id
from group_roles
union
select role_id
from user_roles
union
select role_id
from managed_group_roles
),
roles (role_id, grant_scope_id) as (
select iam_role.public_id,
iam_role.grant_scope_id
from iam_role
where public_id in (select role_id from user_group_roles)
),
final (role_id, role_scope, role_grant) as (
select roles.role_id,
roles.grant_scope_id,
iam_role_grant.canonical_grant
from roles
inner join iam_role_grant
on roles.role_id = iam_role_grant.role_id
-- only retrieves roles with a grant! there can be roles that don't have grants (it's a valid state in boundary)
)
select role_id as role_id, role_scope as scope_id, role_grant as grant from final;
`
)

@ -396,79 +396,8 @@ func (r *Repository) GrantsForUser(ctx context.Context, userId string, _ ...Opti
}
const (
anonUser = `where public_id in (?)`
authUser = `where public_id in ('u_anon', 'u_auth', ?)`
grantsQuery = `
with
users (id) as (
select public_id
from iam_user
%s -- anonUser || authUser
),
user_groups (id) as (
select group_id
from iam_group_member_user,
users
where member_id in (users.id)
),
user_accounts (id) as (
select public_id
from auth_account,
users
where iam_user_id in (users.id)
),
user_managed_groups (id) as (
select managed_group_id
from auth_managed_group_member_account,
user_accounts
where member_id in (user_accounts.id)
),
managed_group_roles (role_id) as (
select role_id
from iam_managed_group_role,
user_managed_groups
where principal_id in (user_managed_groups.id)
),
group_roles (role_id) as (
select role_id
from iam_group_role,
user_groups
where principal_id in (user_groups.id)
),
user_roles (role_id) as (
select role_id
from iam_user_role,
users
where principal_id in (users.id)
),
user_group_roles (role_id) as (
select role_id
from group_roles
union
select role_id
from user_roles
union
select role_id
from managed_group_roles
),
roles (role_id, grant_scope_id) as (
select iam_role.public_id,
iam_role.grant_scope_id
from iam_role,
user_group_roles
where public_id in (user_group_roles.role_id)
),
final (role_id, role_scope, role_grant) as (
select roles.role_id,
roles.grant_scope_id,
iam_role_grant.canonical_grant
from roles
inner
join iam_role_grant
on roles.role_id = iam_role_grant.role_id
)
select role_id as role_id, role_scope as scope_id, role_grant as grant from final;
`
anonUser = `where public_id in (?)`
authUser = `where public_id in ('u_anon', 'u_auth', ?)`
)
var query string

@ -5,10 +5,13 @@ package iam_test
import (
"context"
"encoding/json"
"fmt"
mathrand "math/rand"
"testing"
"github.com/hashicorp/boundary/internal/auth/ldap"
"github.com/hashicorp/boundary/internal/auth/ldap/store"
"github.com/hashicorp/boundary/internal/auth/oidc"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/iam"
@ -16,6 +19,7 @@ import (
"github.com/hashicorp/boundary/internal/types/scope"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
)
func TestGrantsForUser(t *testing.T) {
@ -23,11 +27,16 @@ func TestGrantsForUser(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
wrap := db.TestWrapper(t)
iamRepo := iam.TestRepo(t, conn, wrap)
rw := db.New(conn)
kmsCache := kms.TestKms(t, conn, wrap)
ldapRepo, err := ldap.NewRepository(ctx, rw, rw, kmsCache)
require.NoError(t, err)
userCount := 10
groupCount := 30
managedGroupCount := 30
roleCount := 30
oidcManagedGroupCount := 30
ldapManagedGroupCount := 30
roleCount := 1
// probFactor acts as a mod value; increasing means less probability. 2 =
// 50%, 5 = 20%, etc.
probFactor := 5
@ -45,12 +54,10 @@ func TestGrantsForUser(t *testing.T) {
iam.WithSkipAdminRoleCreation(true),
iam.WithSkipDefaultRoleCreation(true),
)
kmsCache := kms.TestKms(t, conn, wrap)
databaseWrapper, err := kmsCache.GetWrapper(ctx, o.PublicId, kms.KeyPurposeDatabase)
require.NoError(t, err)
authMethod := oidc.TestAuthMethod(
oidcAuthMethod := oidc.TestAuthMethod(
t, conn, databaseWrapper, o.GetPublicId(), oidc.ActivePrivateState,
"alice-rp", "fido",
oidc.WithSigningAlgs(oidc.RS256),
@ -58,23 +65,26 @@ func TestGrantsForUser(t *testing.T) {
oidc.WithApiUrl(oidc.TestConvertToUrls(t, "https://www.alice.com/callback")[0]),
)
// We're going to generate a bunch of users (each tied to an account),
// groups, and managed groups. These will be randomly assigned and we will
// record assignations.
users, accounts := func() (usrs []*iam.User, accts []*oidc.Account) {
ldapAuthMethod := ldap.TestAuthMethod(t, conn, databaseWrapper, o.GetPublicId(), []string{"ldap://test"})
// We're going to generate a bunch of users (each tied to 2 accounts; oidc
// and ldap), groups, and managed groups (oidc and ldap). These will be
// randomly assigned and we will record assignations.
users, oidcAccounts, ldapAccounts := func() (usrs []*iam.User, oidcAccts []*oidc.Account, ldapAccts []*ldap.Account) {
usrs = make([]*iam.User, 0, userCount)
accts = make([]*oidc.Account, 0, userCount)
oidcAccts = make([]*oidc.Account, 0, userCount)
scopeId := scope.Global.String()
if mathrand.Int()%2 == 0 || testManagedGroups {
scopeId = o.GetPublicId()
}
for i := 0; i < userCount; i++ {
accts = append(accts, oidc.TestAccount(t, conn, authMethod, fmt.Sprintf("sub-%d", i)))
oidcAccts = append(oidcAccts, oidc.TestAccount(t, conn, oidcAuthMethod, fmt.Sprintf("sub-%d", i)))
ldapAccts = append(ldapAccts, ldap.TestAccount(t, conn, ldapAuthMethod, fmt.Sprintf("login-name-%d", i)))
usrs = append(usrs, iam.TestUser(
t,
iamRepo,
scopeId,
iam.WithAccountIds(accts[i].PublicId),
iam.WithAccountIds(oidcAccts[i].PublicId, ldapAccts[i].PublicId),
iam.WithName(fmt.Sprintf("testuser%d", i)),
))
}
@ -91,10 +101,18 @@ func TestGrantsForUser(t *testing.T) {
}
return
}()
managedGroups := func() (ret []*oidc.ManagedGroup) {
ret = make([]*oidc.ManagedGroup, 0, managedGroupCount)
for i := 0; i < managedGroupCount; i++ {
ret = append(ret, oidc.TestManagedGroup(t, conn, authMethod, oidc.TestFakeManagedGroupFilter, oidc.WithName(fmt.Sprintf("testmanagedgroup%d", i))))
oidcManagedGroups := func() (ret []*oidc.ManagedGroup) {
ret = make([]*oidc.ManagedGroup, 0, oidcManagedGroupCount)
for i := 0; i < oidcManagedGroupCount; i++ {
ret = append(ret, oidc.TestManagedGroup(t, conn, oidcAuthMethod, oidc.TestFakeManagedGroupFilter, oidc.WithName(fmt.Sprintf("oidc-testmanagedgroup%d", i))))
}
return
}()
ldapManagedGroups := func() (ret []*ldap.ManagedGroup) {
ret = make([]*ldap.ManagedGroup, 0, ldapManagedGroupCount)
for i := 0; i < ldapManagedGroupCount; i++ {
name := fmt.Sprintf("ldap-testmanagedgroup%d", i)
ret = append(ret, ldap.TestManagedGroup(t, conn, ldapAuthMethod, []string{name}, ldap.WithName(ctx, name)))
}
return
}()
@ -131,23 +149,92 @@ func TestGrantsForUser(t *testing.T) {
}
}
}
// This variable stores an easy way to lookup, given a managed group ID, whether a
// user is in that group.
userToManagedGroupsMapping := map[string]map[string]bool{}
// This variable stores an easy way to lookup, given a user id, whether or
// not it's in an oidc managed group.
userToOidcManagedGroupsMapping := map[string]map[string]bool{}
for i, user := range users {
for _, managedGroup := range managedGroups {
for _, managedGroup := range oidcManagedGroups {
// Give each user (account) a chance of being in any specific managed group
if mathrand.Int()%probFactor == 0 {
userId := user.PublicId
accountId := accounts[i].PublicId
accountId := oidcAccounts[i].PublicId
managedGroupId := managedGroup.PublicId
oidc.TestManagedGroupMember(t, conn, managedGroupId, accountId)
currentMapping := userToManagedGroupsMapping[userId]
currentMapping := userToOidcManagedGroupsMapping[userId]
if currentMapping == nil {
currentMapping = make(map[string]bool)
}
currentMapping[managedGroupId] = true
userToManagedGroupsMapping[userId] = currentMapping
userToOidcManagedGroupsMapping[userId] = currentMapping
}
}
}
ldapAcctCloneFunc := func(a *ldap.Account) *ldap.Account {
cp := proto.Clone(a.Account)
return &ldap.Account{
Account: cp.(*store.Account),
}
}
// This variable stores an easy way to lookup, given a user id, whether or
// not it's in an ldap managed group.
userToLdapManagedGroupsMapping := map[string]map[string]bool{}
// This variable stores an easy way to lookup, giving an ldap managed group
// id, whether or not it has a user id
ldapManagedGroupToUser := map[string]map[string]bool{}
for i, user := range users {
userLdapAcct := ldapAccounts[i] // the first acct goes with the first user
acctClone := ldapAcctCloneFunc(userLdapAcct) // clone it just in case it's changed during a db update
for _, managedGroup := range ldapManagedGroups {
// Give each user (account) a chance of being in any specific managed group
if mathrand.Int()%probFactor == 0 {
var existingAcctGroups []string
if acctClone.GetMemberOfGroups() != "" {
require.NoError(t, json.Unmarshal([]byte(acctClone.GetMemberOfGroups()), &existingAcctGroups))
}
var existingManagedGroups []string
require.NoError(t, json.Unmarshal([]byte(managedGroup.GetGroupNames()), &existingManagedGroups))
newGrps, err := json.Marshal(append(existingAcctGroups, existingManagedGroups...))
require.NoError(t, err)
acctClone.MemberOfGroups = string(newGrps)
updated, err := rw.Update(ctx, acctClone, []string{"MemberOfGroups"}, nil)
require.NoError(t, err)
require.Equal(t, 1, updated)
userId := user.GetPublicId()
currentMapping := userToLdapManagedGroupsMapping[userId]
if currentMapping == nil {
currentMapping = make(map[string]bool)
}
currentMapping[managedGroup.GetPublicId()] = true
userToLdapManagedGroupsMapping[userId] = currentMapping
currentMapGrpsToUser := ldapManagedGroupToUser[managedGroup.GetPublicId()]
if currentMapGrpsToUser == nil {
currentMapGrpsToUser = make(map[string]bool)
}
currentMapGrpsToUser[userId] = true
ldapManagedGroupToUser[managedGroup.GetPublicId()] = currentMapGrpsToUser
// check that the acct is part of the managed grp
// 1) check acct is returned from
// auth_managed_group_member_account search
// 2) check that acct belongs to the user
memberAccts, err := ldapRepo.ListManagedGroupMembershipsByMember(ctx, userLdapAcct.GetPublicId())
require.NoError(t, err)
require.GreaterOrEqual(t, len(memberAccts), 1)
found := false
for _, m := range memberAccts {
if m.GetManagedGroupId() == managedGroup.GetPublicId() && m.GetMemberId() == userLdapAcct.GetPublicId() {
found = true
}
}
require.Truef(t, found, "did not find acct in managed grp search")
accts, err := iamRepo.ListUserAccounts(ctx, userId)
require.NoError(t, err)
require.Contains(t, accts, userLdapAcct.GetPublicId())
}
}
}
@ -156,7 +243,8 @@ func TestGrantsForUser(t *testing.T) {
// store mappings
userToRolesMapping := map[string]map[string]bool{}
groupToRolesMapping := map[string]map[string]bool{}
managedGroupToRolesMapping := map[string]map[string]bool{}
oidcManagedGroupToRolesMapping := map[string]map[string]bool{}
ldapManagedGroupToRolesMapping := map[string]map[string]bool{}
if addUsersDirectly {
for _, role := range roles {
for _, user := range users {
@ -194,19 +282,53 @@ func TestGrantsForUser(t *testing.T) {
}
}
for _, role := range roles {
for _, managedGroup := range managedGroups {
// Give each managed group a chance of being directly added to any
// specific role
roleId := role.PublicId
for _, oidcManagedGroup := range oidcManagedGroups {
// Give each oidc managed group a chance of being directly added to
// any specific role
if mathrand.Int()%probFactor == 0 {
roleId := role.PublicId
managedGroupId := managedGroup.PublicId
managedGroupId := oidcManagedGroup.PublicId
iam.TestManagedGroupRole(t, conn, roleId, managedGroupId)
currentMapping := managedGroupToRolesMapping[managedGroupId]
currentMapping := oidcManagedGroupToRolesMapping[managedGroupId]
if currentMapping == nil {
currentMapping = make(map[string]bool)
}
currentMapping[roleId] = true
managedGroupToRolesMapping[managedGroupId] = currentMapping
oidcManagedGroupToRolesMapping[managedGroupId] = currentMapping
}
}
for _, ldapManagedGroup := range ldapManagedGroups {
// Give each ldap managed group a chance of being directly added to
// any specific role
if mathrand.Int()%probFactor == 0 {
ldapManagedGroupId := ldapManagedGroup.GetPublicId()
iam.TestManagedGroupRole(t, conn, roleId, ldapManagedGroupId)
currentMapping := ldapManagedGroupToRolesMapping[ldapManagedGroupId]
if currentMapping == nil {
currentMapping = make(map[string]bool)
}
currentMapping[roleId] = true
ldapManagedGroupToRolesMapping[ldapManagedGroupId] = currentMapping
// just check if role shows up for the user now.
for userId := range ldapManagedGroupToUser[ldapManagedGroupId] {
tuples, err := iamRepo.GrantsForUser(ctx, userId)
t.Log("userId/tuples:", userId, tuples)
require.NoError(t, err)
found := false
foundRoles := []string{}
for _, gt := range tuples {
foundRoles = append(foundRoles, gt.RoleId)
if gt.RoleId == roleId {
found = true
break
}
}
if found {
t.Log("FOUND:", userId, ldapManagedGroupId, foundRoles)
}
assert.Truef(t, found, "did not find role id %s in grants for user %s, grp %s, found user roles %s", roleId, userId, ldapManagedGroupId, foundRoles)
}
}
}
}
@ -214,7 +336,7 @@ func TestGrantsForUser(t *testing.T) {
// Now, fetch the set of grants. We're going to be testing this by looking
// at the role IDs of the matching grant tuples.
for _, user := range users {
var rolesFromUsers, rolesFromGroups, rolesFromManagedGroups int
var rolesFromUsers, rolesFromGroups, rolesFromOidcManagedGroups, rolesFromLdapManagedGroups int
tuples, err := iamRepo.GrantsForUser(ctx, user.PublicId)
require.NoError(t, err)
@ -240,16 +362,30 @@ func TestGrantsForUser(t *testing.T) {
rolesFromGroups++
}
}
for managedGroupId := range userToManagedGroupsMapping[user.PublicId] {
for roleId := range managedGroupToRolesMapping[managedGroupId] {
for managedGroupId := range userToOidcManagedGroupsMapping[user.PublicId] {
for roleId := range oidcManagedGroupToRolesMapping[managedGroupId] {
expectedRoleIds[roleId] = true
rolesFromOidcManagedGroups++
}
}
for managedGroupId := range userToLdapManagedGroupsMapping[user.PublicId] {
for roleId := range ldapManagedGroupToRolesMapping[managedGroupId] {
if !expectedRoleIds[roleId] {
t.Log("Adding ldap role: ", roleId)
}
expectedRoleIds[roleId] = true
rolesFromManagedGroups++
rolesFromLdapManagedGroups++
}
}
// Now verify that the expected set and returned set match
assert.EqualValues(t, expectedRoleIds, roleIds)
require.EqualValues(t, expectedRoleIds, roleIds)
t.Log("finished user", user.PublicId, "total roles", len(expectedRoleIds), "roles from users", rolesFromUsers, "roles from groups", rolesFromGroups, "roles from managed groups", rolesFromManagedGroups)
t.Log("finished user", user.PublicId,
"total roles", len(expectedRoleIds),
", roles from users", rolesFromUsers,
", roles from groups", rolesFromGroups,
", roles from oidc managed groups", rolesFromOidcManagedGroups,
", roles from ldap managed groups", rolesFromLdapManagedGroups)
}
}

Loading…
Cancel
Save