You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
boundary/internal/auth/ldap/repository_managed_group_me...

237 lines
7.2 KiB

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package ldap_test
import (
"context"
"encoding/json"
"math/rand"
"testing"
"time"
"github.com/hashicorp/boundary/internal/auth/ldap"
"github.com/hashicorp/boundary/internal/auth/oidc/store"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_ManagedGroupMemberships(t *testing.T) {
t.Parallel()
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)
testCtx := context.Background()
testGlobalDbWrapper, err := testKms.GetWrapper(testCtx, "global", kms.KeyPurposeDatabase)
require.NoError(t, err)
testAuthMethod := ldap.TestAuthMethod(t, testConn, testGlobalDbWrapper, "global", []string{"ldaps://ldap1"})
testAuthMethodStatic := ldap.TestAuthMethod(t, testConn, testGlobalDbWrapper, "global", []string{"ldaps://ldap1"})
repo, err := ldap.NewRepository(testCtx, testRw, testRw, testKms)
require.NoError(t, err)
require.NotNil(t, repo)
// make some groups with GroupNames which will initially match no accounts
mgs := make([]*ldap.ManagedGroup, 0, 100)
for i := 0; i < 100; i++ {
got := ldap.TestManagedGroup(t, testConn, testAuthMethod, []string{"foo", "bar"})
mgs = append(mgs, got)
}
testUser := iam.TestUser(t, iamRepo, "global")
staticAccount := ldap.TestAccount(t, testConn, testAuthMethodStatic, "test-static-login-name", ldap.WithMemberOfGroups(testCtx, "static"))
staticGroup := ldap.TestManagedGroup(t, testConn, testAuthMethod, []string{"static"})
const staticMembershipCount = 1
testGroupNames := []string{"admin", "users"}
testGroupNamesEncodes, err := json.Marshal(testGroupNames)
require.NoError(t, err)
// Fetch existing default admin user u_1234567890 which will have 20 static
// groups associated with it. Then associate a new ldap account to that
// user
account := ldap.TestAccount(t, testConn, testAuthMethod, "test-login-name", ldap.WithMemberOfGroups(testCtx, testGroupNames...))
adminUser, _, err := iamRepo.LookupUser(testCtx, testUser.PublicId)
require.NoError(t, err)
accts, err := iamRepo.AddUserAccounts(testCtx, testUser.PublicId, adminUser.Version, []string{account.PublicId, staticAccount.PublicId})
require.NoError(t, err)
require.Len(t, accts, 2)
tests := []struct {
name string
account *ldap.Account
wantMgsCount int
specificMgs []*ldap.ManagedGroup
wantErr errors.Code
wantErrContains string
}{
{
name: "valid fixed",
account: account,
specificMgs: mgs[0:20],
},
{
name: "valid fixed, same values",
account: account,
specificMgs: mgs[0:20],
},
{
name: "valid fixed, new values",
account: account,
specificMgs: mgs[20:40],
},
{
name: "valid none",
account: account,
wantMgsCount: 0,
},
{
name: "valid none, second test, testing gracefully aborting",
account: account,
wantMgsCount: 0,
},
{
name: "valid fixed, prep for random",
account: account,
specificMgs: mgs[20:50],
},
{
name: "valid random",
account: account,
wantMgsCount: 30,
},
{
name: "valid random, second test",
account: account,
wantMgsCount: 20,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
// We are intentionally carrying things over between tests to be
// more realistic but that means we need correct versions, so update
// them first.
currMgs, ttime, err := repo.ListManagedGroups(testCtx, testAuthMethod.PublicId)
require.NoError(err)
assert.True(time.Now().Before(ttime.Add(10 * time.Second)))
assert.True(time.Now().After(ttime.Add(-10 * time.Second)))
require.Len(currMgs, 101)
currVersionMap := make(map[string]uint32, len(currMgs))
for _, currMg := range currMgs {
currVersionMap[currMg.PublicId] = currMg.Version
}
for _, mg := range mgs {
mg.Version = currVersionMap[mg.PublicId]
}
var mgsToTest []*ldap.ManagedGroup
var finalMgs map[string]*ldap.ManagedGroup
mgsToTest = tc.specificMgs
if mgsToTest == nil {
// Select at random
mgsToTest = make([]*ldap.ManagedGroup, tc.wantMgsCount)
for i := 0; i < tc.wantMgsCount; i++ {
mg := mgs[rand.Int()%len(mgs)]
mgsToTest[i] = mg
}
}
finalMgs = make(map[string]*ldap.ManagedGroup)
for _, v := range mgsToTest {
v.GroupNames = string(testGroupNamesEncodes)
v, _, err = repo.UpdateManagedGroup(testCtx, "global", v, v.Version, []string{"GroupNames"})
require.NoError(err)
finalMgs[v.PublicId] = v
}
// Ensure the same set was found; all memberships found should have
// been in the finalMgs map, and when they are all removed there
// should be nothing left.
for _, mship := range mgsToTest {
// Randomly check a few to ensure the MembershipsByGroup function works
members, err := repo.ListManagedGroupMembershipsByGroup(testCtx, mship.PublicId)
require.NoError(err)
require.NotEmpty(members)
var found bool
for _, v := range members {
if v.MemberId == tc.account.GetPublicId() {
found = true
break
}
}
assert.True(found)
delete(finalMgs, mship.PublicId)
}
assert.Len(finalMgs, 0)
// Now check that the static account still has the same memberships
memberships, err := repo.ListManagedGroupMembershipsByMember(testCtx, staticAccount.PublicId)
require.NoError(err)
assert.Len(memberships, staticMembershipCount)
assert.Equal(memberships[0].ManagedGroupId, staticGroup.PublicId)
})
}
t.Run("ListManagedGroupMembershipsByGroup-invalid-parameters", func(t *testing.T) {
got, err := repo.ListManagedGroupMembershipsByGroup(testCtx, "")
assert.Error(t, err)
assert.Contains(t, err.Error(), "missing managed group id")
assert.Nil(t, got)
})
t.Run("ListManagedGroupMembershipsByMember-invalid-parameter", func(t *testing.T) {
got, err := repo.ListManagedGroupMembershipsByMember(testCtx, "")
assert.Error(t, err)
assert.Contains(t, err.Error(), "missing account id")
assert.Nil(t, got)
})
}
func TestManagedGroupMemberAccount_SetTableName(t *testing.T) {
t.Parallel()
allocFn := func() *ldap.ManagedGroupMemberAccount {
return &ldap.ManagedGroupMemberAccount{
ManagedGroupMemberAccount: &store.ManagedGroupMemberAccount{},
}
}
defaultTableName := "auth_ldap_managed_group_member_account"
tests := []struct {
name string
setNameTo string
want string
}{
{
name: "new-name",
setNameTo: "new-name",
want: "new-name",
},
{
name: "reset to default",
setNameTo: "",
want: defaultTableName,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
def := allocFn()
require.Equal(defaultTableName, def.TableName())
m := allocFn()
m.SetTableName(tc.setNameTo)
assert.Equal(tc.want, m.TableName())
})
}
}