// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 package alias import ( "context" "testing" pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services" "github.com/stretchr/testify/assert" "google.golang.org/protobuf/reflect/protoreflect" ) func TestRegisterAliasableFields(t *testing.T) { // When this package is imported the aliasable fields are registered so // we can immediately assert that some of the expected fields are present. successCases := []protoreflect.FullName{ (&pbs.GetTargetRequest{}).ProtoReflect().Descriptor().Fields().ByName("id").FullName(), (&pbs.UpdateTargetRequest{}).ProtoReflect().Descriptor().Fields().ByName("id").FullName(), (&pbs.DeleteTargetRequest{}).ProtoReflect().Descriptor().Fields().ByName("id").FullName(), (&pbs.AddTargetHostSourcesRequest{}).ProtoReflect().Descriptor().Fields().ByName("id").FullName(), (&pbs.SetTargetHostSourcesRequest{}).ProtoReflect().Descriptor().Fields().ByName("id").FullName(), (&pbs.RemoveTargetHostSourcesRequest{}).ProtoReflect().Descriptor().Fields().ByName("id").FullName(), (&pbs.AddTargetCredentialSourcesRequest{}).ProtoReflect().Descriptor().Fields().ByName("id").FullName(), (&pbs.SetTargetCredentialSourcesRequest{}).ProtoReflect().Descriptor().Fields().ByName("id").FullName(), (&pbs.RemoveTargetCredentialSourcesRequest{}).ProtoReflect().Descriptor().Fields().ByName("id").FullName(), (&pbs.AuthorizeSessionRequest{}).ProtoReflect().Descriptor().Fields().ByName("id").FullName(), } for _, c := range successCases { t.Run(string(c), func(t *testing.T) { _, ok := globalAliasableRegistry.Load(c) assert.Truef(t, ok, "expected field %q to be aliasable", c) }) } failCases := []protoreflect.FullName{ (&pbs.GetAccountRequest{}).ProtoReflect().Descriptor().Fields().ByName("id").FullName(), (&pbs.UpdateAccountRequest{}).ProtoReflect().Descriptor().Fields().ByName("id").FullName(), (&pbs.DeleteAccountRequest{}).ProtoReflect().Descriptor().Fields().ByName("id").FullName(), } for _, c := range failCases { t.Run(string(c), func(t *testing.T) { _, ok := globalAliasableRegistry.Load(c) assert.Falsef(t, ok, "expected field %q to not be aliasable", c) }) } } func TestResolveAliasFields(t *testing.T) { t.Run("no alias", func(t *testing.T) { ctx := context.Background() m := aliasMapping{m: make(map[string]*Alias)} req := &pbs.GetTargetRequest{Id: "foo"} ctx, err := ResolveRequestIds(ctx, req, m) assert.ErrorContains(t, err, "resource alias not found with value") assert.Nil(t, FromContext(ctx)) }) t.Run("alias", func(t *testing.T) { ctx := context.Background() m := aliasMapping{m: make(map[string]*Alias)} m.m["foo"] = &Alias{PublicId: "alt_1234", Value: "foo", DestinationId: "ttcp_mapped"} req := &pbs.GetTargetRequest{Id: "foo"} ctx, err := ResolveRequestIds(ctx, req, m) assert.NoError(t, err) assert.Equal(t, "ttcp_mapped", req.Id) assert.NotNil(t, FromContext(ctx)) }) t.Run("public id", func(t *testing.T) { ctx := context.Background() m := aliasMapping{m: make(map[string]*Alias)} m.m["foo"] = &Alias{PublicId: "alt_1234", Value: "foo", DestinationId: "ttcp_mapped"} req := &pbs.GetTargetRequest{Id: "ttcp_existing"} ctx, err := ResolveRequestIds(ctx, req, m) assert.NoError(t, err) assert.Equal(t, "ttcp_existing", req.Id) assert.Nil(t, FromContext(ctx)) }) t.Run("alias has no destination id", func(t *testing.T) { ctx := context.Background() m := aliasMapping{m: make(map[string]*Alias)} m.m["foo"] = &Alias{PublicId: "alt_1234", Value: "foo"} req := &pbs.GetTargetRequest{Id: "foo"} ctx, err := ResolveRequestIds(ctx, req, m) assert.ErrorContains(t, err, "resource not found for alias value") assert.Nil(t, FromContext(ctx)) }) // Authorize sessions allow target names to be passed in through the id field // the only way to tell if that is happening is if the scope id or scope name // are also present. t.Run("authorize session target name with scope id", func(t *testing.T) { ctx := context.Background() m := aliasMapping{m: make(map[string]*Alias)} m.m["foo"] = &Alias{PublicId: "alt_1234", Value: "foo", DestinationId: "ttcp_mapped"} req := &pbs.AuthorizeSessionRequest{Id: "foo", ScopeId: "scope_id"} ctx, err := ResolveRequestIds(ctx, req, m) assert.NoError(t, err) assert.Equal(t, "foo", req.Id) assert.Nil(t, FromContext(ctx)) }) t.Run("authorize session target name with scope name", func(t *testing.T) { ctx := context.Background() m := aliasMapping{m: make(map[string]*Alias)} m.m["foo"] = &Alias{PublicId: "alt_1234", Value: "foo", DestinationId: "ttcp_mapped"} req := &pbs.AuthorizeSessionRequest{Id: "foo", ScopeName: "scope_name"} ctx, err := ResolveRequestIds(ctx, req, m) assert.NoError(t, err) assert.Equal(t, "foo", req.Id) assert.Nil(t, FromContext(ctx)) }) t.Run("authorize session alias", func(t *testing.T) { ctx := context.Background() m := aliasMapping{m: make(map[string]*Alias)} m.m["foo"] = &Alias{PublicId: "alt_1234", Value: "foo", DestinationId: "ttcp_mapped"} req := &pbs.AuthorizeSessionRequest{Id: "foo"} ctx, err := ResolveRequestIds(ctx, req, m) assert.NoError(t, err) assert.Equal(t, "ttcp_mapped", req.Id) assert.NotNil(t, FromContext(ctx)) }) } type aliasMapping struct { m map[string]*Alias } func (a aliasMapping) lookupAliasByValue(ctx context.Context, value string) (*Alias, error) { return a.m[value], nil }