diff --git a/internal/db/schema/migrations/oss/postgres_16_05_test.go b/internal/db/schema/migrations/oss/postgres_16_05_test.go index b63444085..a6c4bc081 100644 --- a/internal/db/schema/migrations/oss/postgres_16_05_test.go +++ b/internal/db/schema/migrations/oss/postgres_16_05_test.go @@ -168,8 +168,7 @@ func testSessionCredentialParams(t *testing.T, conn *db.DB, kms *kms.Kms, wrappe libIds := vault.TestCredentialLibraries(t, conn, wrapper, stores[0].GetPublicId(), 2) libs := []*target.CredentialLibrary{ target.TestNewCredentialLibrary(tar.GetPublicId(), libIds[0].GetPublicId(), credential.ApplicationPurpose), - target.TestNewCredentialLibrary(tar.GetPublicId(), libIds[0].GetPublicId(), credential.IngressPurpose), - target.TestNewCredentialLibrary(tar.GetPublicId(), libIds[1].GetPublicId(), credential.EgressPurpose), + target.TestNewCredentialLibrary(tar.GetPublicId(), libIds[1].GetPublicId(), credential.ApplicationPurpose), } targetRepo, err := target.NewRepository(rw, rw, kms) @@ -178,8 +177,7 @@ func testSessionCredentialParams(t *testing.T, conn *db.DB, kms *kms.Kms, wrappe require.NoError(t, err) creds := []*session.DynamicCredential{ session.NewDynamicCredential(libIds[0].GetPublicId(), credential.ApplicationPurpose), - session.NewDynamicCredential(libIds[0].GetPublicId(), credential.IngressPurpose), - session.NewDynamicCredential(libIds[1].GetPublicId(), credential.EgressPurpose), + session.NewDynamicCredential(libIds[1].GetPublicId(), credential.ApplicationPurpose), } return creds } diff --git a/internal/session/repository_session_test.go b/internal/session/repository_session_test.go index f2107a71d..1bc59ee9d 100644 --- a/internal/session/repository_session_test.go +++ b/internal/session/repository_session_test.go @@ -1661,16 +1661,14 @@ func testSessionCredentialParams(t *testing.T, conn *db.DB, wrapper wrapping.Wra libIds := vault.TestCredentialLibraries(t, conn, wrapper, stores[0].GetPublicId(), 2) libs := []*target.CredentialLibrary{ target.TestNewCredentialLibrary(tar.GetPublicId(), libIds[0].GetPublicId(), credential.ApplicationPurpose), - target.TestNewCredentialLibrary(tar.GetPublicId(), libIds[0].GetPublicId(), credential.IngressPurpose), - target.TestNewCredentialLibrary(tar.GetPublicId(), libIds[1].GetPublicId(), credential.EgressPurpose), + target.TestNewCredentialLibrary(tar.GetPublicId(), libIds[1].GetPublicId(), credential.ApplicationPurpose), } _, _, _, err = targetRepo.AddTargetCredentialSources(ctx, tar.GetPublicId(), tar.GetVersion(), libs) require.NoError(err) creds := []*DynamicCredential{ NewDynamicCredential(libIds[0].GetPublicId(), credential.ApplicationPurpose), - NewDynamicCredential(libIds[0].GetPublicId(), credential.IngressPurpose), - NewDynamicCredential(libIds[1].GetPublicId(), credential.EgressPurpose), + NewDynamicCredential(libIds[1].GetPublicId(), credential.ApplicationPurpose), } params.DynamicCredentials = creds return params diff --git a/internal/target/registry.go b/internal/target/registry.go index d33f3035c..333cdd725 100644 --- a/internal/target/registry.go +++ b/internal/target/registry.go @@ -15,10 +15,15 @@ type AllocFunc func() Target // be used by the Repository. type VetFunc func(context.Context, Target) error +// VetCredentialLibrariesFunc is a function that checks the given CredentialLibraries +// to ensure that they are valid for a Target subtype. +type VetCredentialLibrariesFunc func(context.Context, []*CredentialLibrary) error + type registryEntry struct { - alloc AllocFunc - vet VetFunc - prefix string + alloc AllocFunc + vet VetFunc + vetCredentialLibraries VetCredentialLibrariesFunc + prefix string } type registry struct { @@ -71,6 +76,14 @@ func (r *registry) vetFunc(s subtypes.Subtype) (VetFunc, bool) { return entry.vet, ok } +func (r *registry) vetCredentialLibrariesFunc(s subtypes.Subtype) (VetCredentialLibrariesFunc, bool) { + entry, ok := r.get(s) + if !ok { + return nil, ok + } + return entry.vetCredentialLibraries, ok +} + func (r *registry) idPrefix(s subtypes.Subtype) (string, bool) { entry, ok := r.get(s) if !ok { @@ -103,10 +116,11 @@ func SubtypeFromId(id string) subtypes.Subtype { // Register registers repository hooks and the prefixes for a provided Subtype. Register // panics if the subtype has already been registered or if any of the // prefixes are associated with another subtype. -func Register(s subtypes.Subtype, af AllocFunc, vf VetFunc, prefix string) { +func Register(s subtypes.Subtype, af AllocFunc, vf VetFunc, vclf VetCredentialLibrariesFunc, prefix string) { subtypeRegistry.set(s, ®istryEntry{ - alloc: af, - vet: vf, - prefix: prefix, + alloc: af, + vet: vf, + vetCredentialLibraries: vclf, + prefix: prefix, }) } diff --git a/internal/target/repository_credential_source.go b/internal/target/repository_credential_source.go index 2cad2a345..8d158b885 100644 --- a/internal/target/repository_credential_source.go +++ b/internal/target/repository_credential_source.go @@ -74,6 +74,14 @@ func (r *Repository) AddTargetCredentialSources(ctx context.Context, targetId st return nil, nil, nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%s is an unsupported target type %s", t.PublicId, t.Type)) } + vetCredentialLibraries, ok := subtypeRegistry.vetCredentialLibrariesFunc(t.Subtype()) + if !ok { + return nil, nil, nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%s is an unsupported target type %s", t.PublicId, t.Type)) + } + if err := vetCredentialLibraries(ctx, cls); err != nil { + return nil, nil, nil, err + } + target := alloc() target.SetPublicId(ctx, t.PublicId) target.SetVersion(targetVersion + 1) @@ -284,6 +292,15 @@ func (r *Repository) SetTargetCredentialSources(ctx context.Context, targetId st if !ok { return nil, nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%s is an unsupported target type %s", t.PublicId, t.Type)) } + + vetCredentialLibraries, ok := subtypeRegistry.vetCredentialLibrariesFunc(t.Subtype()) + if !ok { + return nil, nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%s is an unsupported target type %s", t.PublicId, t.Type)) + } + if err := vetCredentialLibraries(ctx, cls); err != nil { + return nil, nil, db.NoRowsAffected, err + } + target := alloc() target.SetPublicId(ctx, t.PublicId) target.SetVersion(targetVersion + 1) diff --git a/internal/target/repository_credential_source_test.go b/internal/target/repository_credential_source_test.go index 46cf8985c..d03c438f8 100644 --- a/internal/target/repository_credential_source_test.go +++ b/internal/target/repository_credential_source_test.go @@ -17,7 +17,7 @@ import ( ) func TestRepository_SetTargetCredentialSources(t *testing.T) { - target.Register(targettest.Subtype, targettest.Alloc, targettest.Vet, targettest.TargetPrefix) + target.Register(targettest.Subtype, targettest.Alloc, targettest.Vet, targettest.VetCredentialLibraries, targettest.TargetPrefix) t.Parallel() conn, _ := db.TestSetup(t, "postgres") @@ -189,15 +189,19 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) { origCredSources, origCredLibraries = tt.setup(tar) } - wantCredSources := make(map[string]*target.CredentialLibrary) + wantCredSources := make(map[string]target.CredentialSource) for _, cl := range tt.args.cls { cl.TargetId = tar.GetPublicId() - wantCredSources[cl.CredentialLibraryId+"_"+cl.CredentialPurpose] = cl + wantCredSources[cl.CredentialLibraryId+"_"+cl.CredentialPurpose] = &target.TargetLibrary{ + CredentialLibrary: cl.CredentialLibrary, + } } if tt.args.addToOrigLibs { tt.args.cls = append(tt.args.cls, origCredLibraries...) for _, cl := range origCredLibraries { - wantCredSources[cl.CredentialLibraryId+"_"+cl.CredentialPurpose] = cl + wantCredSources[cl.CredentialLibraryId+"_"+cl.CredentialPurpose] = &target.TargetLibrary{ + CredentialLibrary: cl.CredentialLibrary, + } } } @@ -221,8 +225,8 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) { for _, cs := range got { w, ok := wantCredSources[cs.Id()+"_"+string(cs.CredentialPurpose())] assert.True(ok, "got unexpected credentialsource %v", cs) - assert.Equal(w.CredentialLibraryId, cs.Id()) - assert.Equal(w.CredentialPurpose, string(cs.CredentialPurpose())) + assert.Equal(w.Id(), cs.Id()) + assert.Equal(w.CredentialPurpose(), cs.CredentialPurpose()) } foundTarget, _, _, err := repo.LookupTarget(context.Background(), tar.GetPublicId()) diff --git a/internal/target/targettest/target.go b/internal/target/targettest/target.go index 4109fa465..4d9b3e31b 100644 --- a/internal/target/targettest/target.go +++ b/internal/target/targettest/target.go @@ -203,6 +203,11 @@ func Vet(ctx context.Context, t target.Target) error { return nil } +// VetCredentialLibraries allows for any CredentialLibraries. +func VetCredentialLibraries(_ context.Context, _ []*target.CredentialLibrary) error { + return nil +} + // New creates a targettest.Target. func New(scopeId string, opt ...target.Option) (*Target, error) { const op = "target_test.New" diff --git a/internal/target/tcp/register.go b/internal/target/tcp/register.go index 68508d430..943ff8ac8 100644 --- a/internal/target/tcp/register.go +++ b/internal/target/tcp/register.go @@ -2,13 +2,15 @@ package tcp import ( "context" + "fmt" + "github.com/hashicorp/boundary/internal/credential" "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/target" ) func init() { - target.Register(Subtype, allocTarget, vet, TargetPrefix) + target.Register(Subtype, allocTarget, vet, vetCredentialLibraries, TargetPrefix) } const ( @@ -35,3 +37,16 @@ func vet(ctx context.Context, t target.Target) error { } return nil } + +// vetCredentialLibraries checks that all of the provided credential libriaries have a CredentialPurpose +// of ApplicationPurpose. Any other CredentialPurpose will result in an error. +func vetCredentialLibraries(ctx context.Context, cls []*target.CredentialLibrary) error { + const op = "tcp.vetCredentialLibraries" + + for _, cl := range cls { + if cl.CredentialPurpose != string(credential.ApplicationPurpose) { + return errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("tcp.Target only supports credential purpose: %q", credential.ApplicationPurpose)) + } + } + return nil +} diff --git a/internal/target/tcp/repository_credential_source_test.go b/internal/target/tcp/repository_credential_source_test.go index 7d1077c14..1b0c80b28 100644 --- a/internal/target/tcp/repository_credential_source_test.go +++ b/internal/target/tcp/repository_credential_source_test.go @@ -2,7 +2,6 @@ package tcp_test import ( "context" - "sort" "testing" "time" @@ -14,6 +13,7 @@ import ( "github.com/hashicorp/boundary/internal/kms" "github.com/hashicorp/boundary/internal/oplog" "github.com/hashicorp/boundary/internal/target" + "github.com/hashicorp/boundary/internal/target/store" "github.com/hashicorp/boundary/internal/target/tcp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -40,14 +40,14 @@ func TestRepository_AddTargetCredentialSources(t *testing.T) { type args struct { targetVersion uint32 - credLibIds []string + cls []*target.CredentialLibrary } tests := []struct { - name string - args args - wantCredLibIds []string - wantErr bool - wantErrCode errors.Code + name string + args args + wantCredSources map[string]target.CredentialSource + wantErr bool + wantErrCode errors.Code }{ { name: "zero-version", @@ -69,34 +69,95 @@ func TestRepository_AddTargetCredentialSources(t *testing.T) { name: "valid-single-source", args: args{ targetVersion: 1, - credLibIds: []string{lib1.PublicId}, + cls: []*target.CredentialLibrary{ + target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose), + }, }, - wantCredLibIds: []string{lib1.PublicId}, - wantErr: false, + wantCredSources: map[string]target.CredentialSource{ + lib1.PublicId + "_" + string(credential.ApplicationPurpose): &target.TargetLibrary{ + CredentialLibrary: &store.CredentialLibrary{ + CredentialLibraryId: lib1.PublicId, + CredentialPurpose: string(credential.ApplicationPurpose), + }, + }, + }, + wantErr: false, }, { name: "valid-multiple-sources", args: args{ targetVersion: 1, - credLibIds: []string{lib1.PublicId, lib2.PublicId, lib3.PublicId}, + cls: []*target.CredentialLibrary{ + target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose), + target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose), + target.TestNewCredentialLibrary("", lib3.PublicId, credential.ApplicationPurpose), + }, }, - wantCredLibIds: []string{lib1.PublicId, lib2.PublicId, lib3.PublicId}, - wantErr: false, + wantCredSources: map[string]target.CredentialSource{ + lib1.PublicId + "_" + string(credential.ApplicationPurpose): &target.TargetLibrary{ + CredentialLibrary: &store.CredentialLibrary{ + CredentialLibraryId: lib1.PublicId, + CredentialPurpose: string(credential.ApplicationPurpose), + }, + }, + lib2.PublicId + "_" + string(credential.ApplicationPurpose): &target.TargetLibrary{ + CredentialLibrary: &store.CredentialLibrary{ + CredentialLibraryId: lib2.PublicId, + CredentialPurpose: string(credential.ApplicationPurpose), + }, + }, + lib3.PublicId + "_" + string(credential.ApplicationPurpose): &target.TargetLibrary{ + CredentialLibrary: &store.CredentialLibrary{ + CredentialLibraryId: lib3.PublicId, + CredentialPurpose: string(credential.ApplicationPurpose), + }, + }, + }, + wantErr: false, }, { name: "invalid-source-id", args: args{ targetVersion: 1, - credLibIds: []string{lib1.PublicId, lib2.PublicId, lib3.PublicId, "invalid-source-id"}, + cls: []*target.CredentialLibrary{ + target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose), + target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose), + target.TestNewCredentialLibrary("", lib3.PublicId, credential.ApplicationPurpose), + target.TestNewCredentialLibrary("", "invalid-source-id", credential.ApplicationPurpose), + }, }, wantErr: true, wantErrCode: errors.NotSpecificIntegrity, }, + { + name: "egress-credential-purpose", + args: args{ + targetVersion: 1, + cls: []*target.CredentialLibrary{ + target.TestNewCredentialLibrary("", lib1.PublicId, credential.EgressPurpose), + }, + }, + wantErr: true, + wantErrCode: errors.InvalidParameter, + }, + { + name: "ingress-credential-purpose", + args: args{ + targetVersion: 1, + cls: []*target.CredentialLibrary{ + target.TestNewCredentialLibrary("", lib1.PublicId, credential.IngressPurpose), + }, + }, + wantErr: true, + wantErrCode: errors.InvalidParameter, + }, { name: "bad-version", args: args{ targetVersion: 1000, - credLibIds: []string{lib1.PublicId}, + cls: []*target.CredentialLibrary{ + target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose), + }, }, wantErr: true, wantErrCode: errors.VersionMismatch, @@ -107,25 +168,25 @@ func TestRepository_AddTargetCredentialSources(t *testing.T) { assert, require := assert.New(t), require.New(t) projTarget := tcp.TestTarget(t, conn, staticProj.PublicId, tt.name) - credLibs := make([]*target.CredentialLibrary, 0, len(tt.args.credLibIds)) - for _, clid := range tt.args.credLibIds { - credLibs = append(credLibs, target.TestNewCredentialLibrary(projTarget.PublicId, clid, credential.ApplicationPurpose)) + + for _, cl := range tt.args.cls { + cl.TargetId = projTarget.PublicId } - gotTarget, _, gotCredSources, err := repo.AddTargetCredentialSources(context.Background(), projTarget.PublicId, tt.args.targetVersion, credLibs) + gotTarget, _, gotCredSources, err := repo.AddTargetCredentialSources(context.Background(), projTarget.PublicId, tt.args.targetVersion, tt.args.cls) if tt.wantErr { require.Error(err) assert.Truef(errors.Match(errors.T(tt.wantErrCode), err), "unexpected error %s", err.Error()) return } require.NoError(err) - assert.Len(gotCredSources, len(tt.wantCredLibIds)) - gotCredSourcesMap := map[string]target.CredentialSource{} - for _, s := range gotCredSources { - gotCredSourcesMap[s.Id()] = s - } - for _, id := range tt.wantCredLibIds { - assert.NotEmpty(gotCredSourcesMap[id]) + assert.Len(gotCredSources, len(tt.wantCredSources)) + + for _, cs := range gotCredSources { + w, ok := tt.wantCredSources[cs.Id()+"_"+string(cs.CredentialPurpose())] + assert.True(ok, "got unexpected credentialsource %v", cs) + assert.Equal(w.Id(), cs.Id()) + assert.Equal(w.CredentialPurpose(), cs.CredentialPurpose()) } // test to see of the target version update oplog was created @@ -138,9 +199,13 @@ func TestRepository_AddTargetCredentialSources(t *testing.T) { assert.Equal(projTarget.GetVersion(), tar.GetVersion()-1) assert.True(proto.Equal(gotTarget.(*tcp.Target), tar.(*tcp.Target))) assert.Equal(gotCredSources, lookupCredSources) - for _, s := range lookupCredSources { - assert.NotEmpty(gotCredSourcesMap[s.Id()]) - assert.Equal(projTarget.PublicId, s.TargetId()) + + for _, cs := range lookupCredSources { + w, ok := tt.wantCredSources[cs.Id()+"_"+string(cs.CredentialPurpose())] + assert.True(ok, "got unexpected credentialsource %v", cs) + assert.Equal(w.Id(), cs.Id()) + assert.Equal(w.CredentialPurpose(), cs.CredentialPurpose()) + assert.Equal(projTarget.PublicId, cs.TargetId()) } }) } @@ -402,7 +467,7 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) { } type args struct { targetVersion uint32 - clIds []string + cls []*target.CredentialLibrary addToOrigLibs bool } tests := []struct { @@ -418,7 +483,7 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) { setup: setupFn, args: args{ targetVersion: 2, - clIds: []string{}, + cls: []*target.CredentialLibrary{}, }, wantErr: false, wantAffectedRows: 10, @@ -428,7 +493,7 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) { setup: setupFn, args: args{ targetVersion: 2, - clIds: []string{}, + cls: []*target.CredentialLibrary{}, addToOrigLibs: true, }, wantErr: false, @@ -439,7 +504,10 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) { setup: setupFn, args: args{ targetVersion: 2, - clIds: []string{lib1.PublicId, lib2.PublicId}, + cls: []*target.CredentialLibrary{ + target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose), + target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose), + }, addToOrigLibs: true, }, wantErr: false, @@ -450,7 +518,10 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) { setup: setupFn, args: args{ targetVersion: 0, - clIds: []string{lib1.PublicId, lib2.PublicId}, + cls: []*target.CredentialLibrary{ + target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose), + target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose), + }, addToOrigLibs: true, }, wantErr: true, @@ -461,7 +532,10 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) { setup: setupFn, args: args{ targetVersion: 1000, - clIds: []string{lib1.PublicId, lib2.PublicId}, + cls: []*target.CredentialLibrary{ + target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose), + target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose), + }, addToOrigLibs: true, }, wantErr: true, @@ -472,12 +546,39 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) { setup: setupFn, args: args{ targetVersion: 2, - clIds: []string{lib1.PublicId, lib2.PublicId}, + cls: []*target.CredentialLibrary{ + target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose), + target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose), + }, addToOrigLibs: false, }, wantErr: false, wantAffectedRows: 12, }, + { + name: "egress-credential-purpose", + setup: setupFn, + args: args{ + targetVersion: 1, + cls: []*target.CredentialLibrary{ + target.TestNewCredentialLibrary("", lib1.PublicId, credential.EgressPurpose), + }, + }, + wantErr: true, + wantErrCode: errors.InvalidParameter, + }, + { + name: "ingress-credential-purpose", + setup: setupFn, + args: args{ + targetVersion: 1, + cls: []*target.CredentialLibrary{ + target.TestNewCredentialLibrary("", lib1.PublicId, credential.IngressPurpose), + }, + }, + wantErr: true, + wantErrCode: errors.InvalidParameter, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -491,16 +592,19 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) { origCredSources, origCredLibraries = tt.setup(tar) } - cls := make([]*target.CredentialLibrary, 0, len(tt.args.clIds)) - for _, clid := range tt.args.clIds { - cls = append(cls, target.TestNewCredentialLibrary(tar.GetPublicId(), clid, credential.ApplicationPurpose)) + wantCredSources := make(map[string]target.CredentialSource) + for _, cl := range tt.args.cls { + cl.TargetId = tar.GetPublicId() + wantCredSources[cl.CredentialLibraryId+"_"+cl.CredentialPurpose] = &target.TargetLibrary{ + CredentialLibrary: cl.CredentialLibrary, + } } - var wantIds []string - wantIds = append(wantIds, tt.args.clIds...) if tt.args.addToOrigLibs { - cls = append(cls, origCredLibraries...) + tt.args.cls = append(tt.args.cls, origCredLibraries...) for _, cl := range origCredLibraries { - wantIds = append(wantIds, cl.CredentialLibraryId) + wantCredSources[cl.CredentialLibraryId+"_"+cl.CredentialPurpose] = &target.TargetLibrary{ + CredentialLibrary: cl.CredentialLibrary, + } } } @@ -508,7 +612,7 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) { require.NoError(err) assert.Equal(origCredSources, lookupCredSources) - _, got, affectedRows, err := repo.SetTargetCredentialSources(context.Background(), tar.GetPublicId(), tt.args.targetVersion, cls) + _, got, affectedRows, err := repo.SetTargetCredentialSources(context.Background(), tar.GetPublicId(), tt.args.targetVersion, tt.args.cls) if tt.wantErr { require.Error(err) assert.Equal(0, affectedRows) @@ -519,18 +623,14 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) { require.NoError(err) assert.Equal(tt.wantAffectedRows, affectedRows) - assert.Equal(len(wantIds), len(got)) - sort.Strings(wantIds) + assert.Equal(len(wantCredSources), len(got)) - var gotIds []string - if len(got) > 0 { - gotIds = make([]string, 0, len(got)) - for _, s := range got { - gotIds = append(gotIds, s.Id()) - } + for _, cs := range got { + w, ok := wantCredSources[cs.Id()+"_"+string(cs.CredentialPurpose())] + assert.True(ok, "got unexpected credentialsource %v", cs) + assert.Equal(w.Id(), cs.Id()) + assert.Equal(w.CredentialPurpose(), cs.CredentialPurpose()) } - sort.Strings(gotIds) - assert.Equal(wantIds, gotIds) foundTarget, _, _, err := repo.LookupTarget(context.Background(), tar.GetPublicId()) require.NoError(err)