2024-02-01 07:31:46 -08:00
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package aliases_test
import (
"context"
"errors"
"fmt"
"slices"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/hashicorp/boundary/globals"
"github.com/hashicorp/boundary/internal/alias/target"
"github.com/hashicorp/boundary/internal/auth/password"
"github.com/hashicorp/boundary/internal/authtoken"
"github.com/hashicorp/boundary/internal/daemon/controller/auth"
"github.com/hashicorp/boundary/internal/daemon/controller/handlers"
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/aliases"
"github.com/hashicorp/boundary/internal/db"
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
authpb "github.com/hashicorp/boundary/internal/gen/controller/auth"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/requests"
"github.com/hashicorp/boundary/internal/server"
"github.com/hashicorp/boundary/internal/target/tcp"
"github.com/hashicorp/boundary/internal/types/scope"
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/aliases"
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes"
"google.golang.org/genproto/protobuf/field_mask"
"google.golang.org/grpc/codes"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/timestamppb"
"google.golang.org/protobuf/types/known/wrapperspb"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var testAuthorizedActions = [] string { "no-op" , "read" , "update" , "delete" }
func TestGet ( t * testing . T ) {
ctx := context . Background ()
conn , _ := db . TestSetup ( t , "postgres" )
rw := db . New ( conn )
wrap := db . TestWrapper ( t )
kmsCache := kms . TestKms ( t , conn , wrap )
iamRepo := iam . TestRepo ( t , conn , wrap )
iamRepoFn := func () ( * iam . Repository , error ) {
return iamRepo , nil
}
repoFn := func () ( * target . Repository , error ) {
return target . NewRepository ( ctx , rw , rw , kmsCache )
}
_ , p := iam . TestScopes ( t , iamRepo )
tar := tcp . TestTarget ( ctx , t , conn , p . GetPublicId (), "testTarget" )
og := target . TestAlias ( t , rw , "test.get" , target . WithName ( "alias name" ), target . WithDescription ( "default" ), target . WithDestinationId ( tar . GetPublicId ()), target . WithHostId ( "hst_1234567890" ))
toMerge := & pbs . GetAliasRequest {
Id : og . GetPublicId (),
}
globalScopeInfo := & scopes . ScopeInfo { Id : scope . Global . String (), Type : scope . Global . String (), Name : "global" , Description : "Global Scope" }
wantAlias := & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
Id : og . GetPublicId (),
ScopeId : "global" ,
Scope : globalScopeInfo ,
Name : wrapperspb . String ( og . GetName ()),
Description : wrapperspb . String ( og . GetDescription ()),
CreatedTime : og . CreateTime . GetTimestamp (),
UpdatedTime : og . UpdateTime . GetTimestamp (),
Value : og . GetValue (),
Version : 1 ,
DestinationId : wrapperspb . String ( og . GetDestinationId ()),
Attrs : & pb . Alias_TargetAliasAttributes {
TargetAliasAttributes : & pb . TargetAliasAttributes {
AuthorizeSessionArguments : & pb . AuthorizeSessionArguments {
HostId : og . GetHostId (),
},
},
},
AuthorizedActions : testAuthorizedActions ,
}
cases := [] struct {
name string
scopeId string
req * pbs . GetAliasRequest
res * pbs . GetAliasResponse
err error
}{
{
name : "Get an Existing Alias" ,
scopeId : og . GetScopeId (),
req : & pbs . GetAliasRequest { Id : og . GetPublicId ()},
res : & pbs . GetAliasResponse { Item : wantAlias },
},
{
2024-02-29 14:57:38 -08:00
name : "Get a non existent Alias" ,
2024-02-01 07:31:46 -08:00
req : & pbs . GetAliasRequest { Id : globals . TargetAliasPrefix + "_DoesntExis" },
res : nil ,
err : handlers . ApiErrorWithCode ( codes . NotFound ),
},
{
name : "Wrong id prefix" ,
req : & pbs . GetAliasRequest { Id : "j_1234567890" },
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "space in id" ,
req : & pbs . GetAliasRequest { Id : globals . TargetAliasPrefix + "_1 23456789" },
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
req := proto . Clone ( toMerge ).( * pbs . GetAliasRequest )
proto . Merge ( req , tc . req )
s , err := aliases . NewService ( ctx , repoFn , iamRepoFn , 1000 )
require . NoError ( err , "Couldn't create new alias service." )
got , gErr := s . GetAlias ( auth . DisabledAuthTestContext ( iamRepoFn , tc . scopeId ), req )
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "GetAlias(%+v) got error %v, wanted %v" , req , gErr , tc . err )
}
assert . Empty ( cmp . Diff (
got ,
tc . res ,
protocmp . Transform (),
cmpopts . SortSlices ( func ( a , b string ) bool {
return a < b
}),
), "GetAlias(%q) got response\n%q, wanted\n%q" , req , got , tc . res )
})
}
}
func TestList ( t * testing . T ) {
ctx := context . Background ()
conn , _ := db . TestSetup ( t , "postgres" )
rw := db . New ( conn )
wrap := db . TestWrapper ( t )
kmsCache := kms . TestKms ( t , conn , wrap )
iamRepo := iam . TestRepo ( t , conn , wrap )
iamRepoFn := func () ( * iam . Repository , error ) {
return iamRepo , nil
}
repo , err := target . NewRepository ( ctx , rw , rw , kmsCache )
require . NoError ( t , err )
repoFn := func () ( * target . Repository , error ) {
return repo , nil
}
2024-02-29 14:42:26 -08:00
var wantGlobalAliases [] * pb . Alias
2024-02-01 07:31:46 -08:00
for i := 0 ; i < 10 ; i ++ {
gg := target . TestAlias ( t , rw , fmt . Sprintf ( "test%d.alias" , i ))
2024-02-29 14:42:26 -08:00
wantGlobalAliases = append ( wantGlobalAliases , & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
Id : gg . GetPublicId (),
ScopeId : gg . GetScopeId (),
Scope : & scopes . ScopeInfo { Id : scope . Global . String (), Type : scope . Global . String (), Name : "global" , Description : "Global Scope" },
CreatedTime : gg . GetCreateTime (). GetTimestamp (),
UpdatedTime : gg . GetUpdateTime (). GetTimestamp (),
Version : 1 ,
Value : gg . GetValue (),
AuthorizedActions : testAuthorizedActions ,
})
}
2024-02-29 14:42:26 -08:00
slices . Reverse ( wantGlobalAliases )
2024-02-01 07:31:46 -08:00
cases := [] struct {
name string
req * pbs . ListAliasesRequest
res * pbs . ListAliasesResponse
err error
}{
{
2024-02-29 14:42:26 -08:00
name : "List Global Aliases" ,
2024-02-01 07:31:46 -08:00
req : & pbs . ListAliasesRequest { ScopeId : "global" },
res : & pbs . ListAliasesResponse {
2024-02-29 14:42:26 -08:00
Items : wantGlobalAliases ,
EstItemCount : uint32 ( len ( wantGlobalAliases )),
2024-02-01 07:31:46 -08:00
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
},
{
2024-02-29 14:42:26 -08:00
name : "List global aliases recursively" ,
2024-02-01 07:31:46 -08:00
req : & pbs . ListAliasesRequest { ScopeId : "global" , Recursive : true },
res : & pbs . ListAliasesResponse {
2024-02-29 14:42:26 -08:00
Items : wantGlobalAliases ,
EstItemCount : uint32 ( len ( wantGlobalAliases )),
2024-02-01 07:31:46 -08:00
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
},
{
2024-02-29 14:42:26 -08:00
name : "Filter to no aliases" ,
2024-02-01 07:31:46 -08:00
req : & pbs . ListAliasesRequest { ScopeId : "global" , Recursive : true , Filter : `"/item/id"=="doesntmatch"` },
res : & pbs . ListAliasesResponse {
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
},
{
name : "Filter Bad Format" ,
req : & pbs . ListAliasesRequest { ScopeId : "global" , Filter : `"//id/"=="bad"` },
err : handlers . InvalidArgumentErrorf ( "bad format" , nil ),
},
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
s , err := aliases . NewService ( ctx , repoFn , iamRepoFn , 1000 )
require . NoError ( err , "Couldn't create new alias service." )
// Test with a non-anon user
got , gErr := s . ListAliases ( auth . DisabledAuthTestContext ( iamRepoFn , tc . req . GetScopeId ()), tc . req )
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "ListAliases(%q) got error %v, wanted %v" , tc . req . GetScopeId (), gErr , tc . err )
return
}
require . NoError ( gErr )
assert . Empty ( cmp . Diff (
got ,
tc . res ,
protocmp . Transform (),
protocmp . IgnoreFields ( & pbs . ListAliasesResponse {}, "list_token" ),
cmpopts . SortSlices ( func ( a , b string ) bool {
return a < b
}),
2024-02-29 14:42:26 -08:00
), "ListAliases(%q) got response %q, wanted %q" , tc . req . GetScopeId (), got , tc . res )
2024-02-01 07:31:46 -08:00
// Test the anon case
got , gErr = s . ListAliases ( auth . DisabledAuthTestContext ( iamRepoFn , tc . req . GetScopeId (), auth . WithUserId ( globals . AnonymousUserId )), tc . req )
require . NoError ( gErr )
assert . Len ( got . Items , len ( tc . res . Items ))
for _ , item := range got . GetItems () {
require . Nil ( item . CreatedTime )
require . Nil ( item . UpdatedTime )
require . Zero ( item . Version )
}
})
}
}
func aliasToProto ( u * target . Alias , si * scopes . ScopeInfo , authorizedActions [] string ) * pb . Alias {
pu := & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
Id : u . GetPublicId (),
Value : u . GetValue (),
ScopeId : u . GetScopeId (),
Scope : si ,
CreatedTime : u . GetCreateTime (). GetTimestamp (),
UpdatedTime : u . GetUpdateTime (). GetTimestamp (),
Version : u . GetVersion (),
AuthorizedActions : testAuthorizedActions ,
}
if u . GetName () != "" {
pu . Name = wrapperspb . String ( u . GetName ())
}
if u . GetDestinationId () != "" {
pu . DestinationId = wrapperspb . String ( u . GetDestinationId ())
}
if u . GetHostId () != "" {
pu . Attrs = & pb . Alias_TargetAliasAttributes {
TargetAliasAttributes : & pb . TargetAliasAttributes {
AuthorizeSessionArguments : & pb . AuthorizeSessionArguments {
HostId : u . GetHostId (),
},
},
}
}
if u . GetDescription () != "" {
pu . Description = wrapperspb . String ( u . GetDescription ())
}
return pu
}
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 )
kmsCache := kms . TestKms ( t , conn , wrapper )
rw := db . New ( conn )
repo , err := target . NewRepository ( ctx , rw , rw , kmsCache )
require . NoError ( t , err )
repoFn := func () ( * target . Repository , error ) {
return repo , nil
}
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 , kmsCache )
}
serversRepoFn := func () ( * server . Repository , error ) {
return server . NewRepository ( ctx , rw , rw , kmsCache )
}
tokenRepo , err := tokenRepoFn ()
require . NoError ( t , err )
// Run analyze to update postgres meta tables
_ , err = sqlDB . ExecContext ( ctx , "analyze" )
require . NoError ( t , err )
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 ))
// add roles to be able to see all users
allowedRole := iam . TestRole ( t , conn , "global" )
iam . TestRoleGrant ( t , conn , allowedRole . GetPublicId (), "id=*;type=*;actions=*" )
iam . TestUserRole ( t , conn , allowedRole . GetPublicId (), u . GetPublicId ())
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 , kmsCache , & requestInfo )
var globalAliases [] * pb . Alias
globalScopeInfo := & scopes . ScopeInfo { Id : scope . Global . String (), Type : scope . Global . String (), Name : "global" , Description : "Global Scope" }
var safeToDeleteAlias string
for i := 0 ; i < 10 ; i ++ {
gg := target . TestAlias ( t , rw , fmt . Sprintf ( "test%d.alias" , i ))
globalAliases = append ( globalAliases , aliasToProto ( gg , globalScopeInfo , testAuthorizedActions ))
safeToDeleteAlias = gg . GetPublicId ()
}
slices . Reverse ( globalAliases )
a , err := aliases . NewService ( ctx , repoFn , iamRepoFn , 1000 )
require . NoError ( t , err , "Couldn't create new alias service." )
// Run analyze to update postgres estimates
_ , err = sqlDB . ExecContext ( context . Background (), "analyze" )
require . NoError ( t , err )
itemCount := uint32 ( len ( globalAliases ))
testPageSize := int (( itemCount - 2 ) / 2 )
// Start paginating, recursively
req := & pbs . ListAliasesRequest {
ScopeId : "global" ,
Recursive : true ,
Filter : "" ,
ListToken : "" ,
PageSize : uint32 ( testPageSize ),
}
got , err := a . ListAliases ( 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 . ListAliasesResponse {
Items : globalAliases [ 0 : testPageSize ],
ResponseType : "delta" ,
SortBy : "created_time" ,
SortDir : "desc" ,
RemovedIds : nil ,
2024-02-29 14:42:26 -08:00
// In addition to the added aliases, there are the aliases added
2024-02-01 07:31:46 -08:00
// 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 . ListAliasesResponse {}, "list_token" ),
),
)
// Request second page
req . ListToken = got . ListToken
got , err = a . ListAliases ( 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 . ListAliasesResponse {
Items : globalAliases [ 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 . ListAliasesResponse {}, "list_token" ),
),
)
// Request rest of results
req . ListToken = got . ListToken
req . PageSize = 10
got , err = a . ListAliases ( 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 . ListAliasesResponse {
Items : globalAliases [ 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 . ListAliasesResponse {}, "list_token" ),
),
)
2024-02-29 14:42:26 -08:00
// Update 2 aliases and see them in the refresh
2024-02-01 07:31:46 -08:00
g1 := globalAliases [ len ( globalAliases ) - 1 ]
g1 . Description = wrapperspb . String ( "updated1" )
resp1 , err := a . UpdateAlias ( ctx , & pbs . UpdateAliasRequest {
Id : g1 . GetId (),
Item : & pb . Alias { Description : g1 . GetDescription (), Version : g1 . GetVersion ()},
UpdateMask : & field_mask . FieldMask { Paths : [] string { "description" }},
})
require . NoError ( t , err )
g1 . UpdatedTime = resp1 . GetItem (). GetUpdatedTime ()
g1 . Version = resp1 . GetItem (). GetVersion ()
globalAliases = append ([] * pb . Alias { g1 }, globalAliases [: len ( globalAliases ) - 1 ] ... )
g2 := globalAliases [ len ( globalAliases ) - 1 ]
g2 . Description = wrapperspb . String ( "updated2" )
resp2 , err := a . UpdateAlias ( ctx , & pbs . UpdateAliasRequest {
Id : g2 . GetId (),
Item : & pb . Alias { Description : g2 . GetDescription (), Version : g2 . GetVersion ()},
UpdateMask : & field_mask . FieldMask { Paths : [] string { "description" }},
})
require . NoError ( t , err )
g2 . UpdatedTime = resp2 . GetItem (). GetUpdatedTime ()
g2 . Version = resp2 . GetItem (). GetVersion ()
globalAliases = append ([] * pb . Alias { g2 }, globalAliases [: len ( globalAliases ) - 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 . ListAliases ( 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 . ListAliasesResponse {
Items : [] * pb . Alias { globalAliases [ 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 . ListAliasesResponse {}, "list_token" ),
),
)
// Get next page
req . ListToken = got . ListToken
got , err = a . ListAliases ( 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 . ListAliasesResponse {
Items : [] * pb . Alias { globalAliases [ 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 . ListAliasesResponse {}, "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` , globalAliases [ len ( globalAliases ) - 2 ]. Id , globalAliases [ len ( globalAliases ) - 1 ]. Id )
got , err = a . ListAliases ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), 1 )
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListAliasesResponse {
Items : [] * pb . Alias { globalAliases [ len ( globalAliases ) - 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 . ListAliasesResponse {}, "list_token" ),
),
)
req . ListToken = got . ListToken
// Get the second page
got , err = a . ListAliases ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), 1 )
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListAliasesResponse {
Items : [] * pb . Alias { globalAliases [ len ( globalAliases ) - 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 . ListAliasesResponse {}, "list_token" ),
),
)
_ , err = repo . DeleteAlias ( ctx , safeToDeleteAlias )
require . NoError ( t , err )
req . ListToken = got . ListToken
got , err = a . ListAliases ( ctx , req )
require . NoError ( t , err )
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListAliasesResponse {
Items : nil ,
ResponseType : "complete" ,
SortBy : "updated_time" ,
SortDir : "desc" ,
RemovedIds : [] string { safeToDeleteAlias },
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListAliasesResponse {}, "list_token" ),
),
)
}
func TestDelete ( t * testing . T ) {
ctx := context . Background ()
conn , _ := db . TestSetup ( t , "postgres" )
rw := db . New ( conn )
wrap := db . TestWrapper ( t )
kmsCache := kms . TestKms ( t , conn , wrap )
iamRepo := iam . TestRepo ( t , conn , wrap )
iamRepoFn := func () ( * iam . Repository , error ) {
return iamRepo , nil
}
_ , p := iam . TestScopes ( t , iamRepo )
repoFn := func () ( * target . Repository , error ) {
return target . NewRepository ( ctx , rw , rw , kmsCache )
}
tar := tcp . TestTarget ( ctx , t , conn , p . GetPublicId (), "testTarget" )
og := target . TestAlias ( t , rw , "test.delete" , target . WithDescription ( "default" ), target . WithDestinationId ( tar . GetPublicId ()), target . WithHostId ( "hst_1234567890" ))
s , err := aliases . NewService ( context . Background (), repoFn , iamRepoFn , 1000 )
require . NoError ( t , err , "Error when getting new alias service." )
cases := [] struct {
name string
scopeId string
req * pbs . DeleteAliasRequest
res * pbs . DeleteAliasResponse
err error
}{
{
name : "Delete an Existing Alias" ,
scopeId : og . GetScopeId (),
req : & pbs . DeleteAliasRequest {
Id : og . GetPublicId (),
},
},
{
name : "Delete bad alias id" ,
scopeId : og . GetScopeId (),
req : & pbs . DeleteAliasRequest {
Id : globals . TargetAliasPrefix + "_doesntexis" ,
},
err : handlers . ApiErrorWithCode ( codes . NotFound ),
},
{
name : "Bad Alias Id formatting" ,
scopeId : og . GetScopeId (),
req : & pbs . DeleteAliasRequest {
Id : "bad_format" ,
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
got , gErr := s . DeleteAlias ( auth . DisabledAuthTestContext ( iamRepoFn , tc . scopeId ), tc . req )
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "DeleteAlias(%+v) got error %v, wanted %v" , tc . req , gErr , tc . err )
}
assert . EqualValuesf ( tc . res , got , "DeleteAlias(%+v) got response %q, wanted %q" , tc . req , got , tc . res )
})
}
}
func TestDelete_twice ( t * testing . T ) {
ctx := context . Background ()
conn , _ := db . TestSetup ( t , "postgres" )
rw := db . New ( conn )
wrap := db . TestWrapper ( t )
kmsCache := kms . TestKms ( t , conn , wrap )
iamRepo := iam . TestRepo ( t , conn , wrap )
iamRepoFn := func () ( * iam . Repository , error ) {
return iamRepo , nil
}
repoFn := func () ( * target . Repository , error ) {
return target . NewRepository ( ctx , rw , rw , kmsCache )
}
og := target . TestAlias ( t , rw , "test.delete" , target . WithDescription ( "default" ))
s , err := aliases . NewService ( context . Background (), repoFn , iamRepoFn , 1000 )
require . NoError ( t , err , "Error when getting new alias service" )
scopeId := og . GetScopeId ()
req := & pbs . DeleteAliasRequest {
Id : og . GetPublicId (),
}
ctx = auth . DisabledAuthTestContext ( iamRepoFn , scopeId )
_ , gErr := s . DeleteAlias ( ctx , req )
assert . NoError ( t , gErr , "First attempt" )
_ , gErr = s . DeleteAlias ( ctx , req )
assert . Error ( t , gErr , "Second attempt" )
assert . True ( t , errors . Is ( gErr , handlers . ApiErrorWithCode ( codes . NotFound )), "Expected permission denied for the second delete." )
}
func TestCreate ( t * testing . T ) {
ctx := context . Background ()
conn , _ := db . TestSetup ( t , "postgres" )
rw := db . New ( conn )
wrap := db . TestWrapper ( t )
kmsCache := kms . TestKms ( t , conn , wrap )
iamRepo := iam . TestRepo ( t , conn , wrap )
iamRepoFn := func () ( * iam . Repository , error ) {
return iamRepo , nil
}
_ , p := iam . TestScopes ( t , iamRepo )
repoFn := func () ( * target . Repository , error ) {
return target . NewRepository ( ctx , rw , rw , kmsCache )
}
tar := tcp . TestTarget ( ctx , t , conn , p . GetPublicId (), "testTarget" )
al := target . TestAlias ( t , rw , "test.duplicated.create" ,
target . WithName ( "alias name" ),
target . WithDestinationId ( tar . GetPublicId ()))
globalScopeInfo := & scopes . ScopeInfo { Id : scope . Global . String (), Type : scope . Global . String (), Name : "global" , Description : "Global Scope" }
cases := [] struct {
name string
req * pbs . CreateAliasRequest
res * pbs . CreateAliasResponse
errContains string
}{
{
name : "Create a valid Alias" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
ScopeId : scope . Global . String (),
Value : "valid.alias" ,
}},
res : & pbs . CreateAliasResponse {
Uri : fmt . Sprintf ( "aliases/%s_" , globals . TargetAliasPrefix ),
Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
ScopeId : scope . Global . String (),
Scope : globalScopeInfo ,
Value : "valid.alias" ,
Version : 1 ,
AuthorizedActions : testAuthorizedActions ,
},
},
},
{
name : "Alias to existing target" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
ScopeId : scope . Global . String (),
Value : "target-assigned.valid.alias" ,
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
}},
res : & pbs . CreateAliasResponse {
Uri : fmt . Sprintf ( "aliases/%s_" , globals . TargetAliasPrefix ),
Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
ScopeId : scope . Global . String (),
Scope : globalScopeInfo ,
Value : "target-assigned.valid.alias" ,
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
Version : 1 ,
AuthorizedActions : testAuthorizedActions ,
},
},
},
2024-04-19 07:49:11 -07:00
{
name : "Alias to poorly formatted target id" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
Type : "target" ,
ScopeId : scope . Global . String (),
Value : "target-assigned.valid.alias" ,
DestinationId : wrapperspb . String ( "this is not a valid target id" ),
}},
errContains : `Incorrectly formatted identifier.` ,
},
2024-02-23 12:02:48 -05:00
{
name : "Alias to existing target with static host id" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
Type : "target" ,
ScopeId : scope . Global . String (),
Value : "target-assigned.valid.alias.two" ,
Attrs : & pb . Alias_TargetAliasAttributes {
TargetAliasAttributes : & pb . TargetAliasAttributes {
AuthorizeSessionArguments : & pb . AuthorizeSessionArguments {
HostId : "hst_1234567890" ,
},
},
},
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
}},
res : & pbs . CreateAliasResponse {
Uri : fmt . Sprintf ( "aliases/%s_" , globals . TargetAliasPrefix ),
Item : & pb . Alias {
Type : "target" ,
ScopeId : scope . Global . String (),
Scope : globalScopeInfo ,
Value : "target-assigned.valid.alias.two" ,
Attrs : & pb . Alias_TargetAliasAttributes {
TargetAliasAttributes : & pb . TargetAliasAttributes {
AuthorizeSessionArguments : & pb . AuthorizeSessionArguments {
HostId : "hst_1234567890" ,
},
},
},
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
Version : 1 ,
AuthorizedActions : testAuthorizedActions ,
},
},
},
{
name : "Alias to existing target with dynamic host id" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
Type : "target" ,
ScopeId : scope . Global . String (),
Value : "target-assigned.valid.alias.three" ,
Attrs : & pb . Alias_TargetAliasAttributes {
TargetAliasAttributes : & pb . TargetAliasAttributes {
AuthorizeSessionArguments : & pb . AuthorizeSessionArguments {
HostId : "hplg_1234567890" ,
},
},
},
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
}},
res : & pbs . CreateAliasResponse {
Uri : fmt . Sprintf ( "aliases/%s_" , globals . TargetAliasPrefix ),
Item : & pb . Alias {
Type : "target" ,
ScopeId : scope . Global . String (),
Scope : globalScopeInfo ,
Value : "target-assigned.valid.alias.three" ,
Attrs : & pb . Alias_TargetAliasAttributes {
TargetAliasAttributes : & pb . TargetAliasAttributes {
AuthorizeSessionArguments : & pb . AuthorizeSessionArguments {
HostId : "hplg_1234567890" ,
},
},
},
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
Version : 1 ,
AuthorizedActions : testAuthorizedActions ,
},
},
},
2024-02-02 14:33:32 -08:00
{
name : "Omitting the alias type" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
ScopeId : scope . Global . String (),
Value : "target-assigned.valid.alias" ,
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
}},
errContains : `This field is required` ,
},
2024-02-01 07:31:46 -08:00
{
name : "host id with no destination target" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
ScopeId : scope . Global . String (),
Value : "host-id.no-destination.alias" ,
Attrs : & pb . Alias_TargetAliasAttributes {
TargetAliasAttributes : & pb . TargetAliasAttributes {
AuthorizeSessionArguments : & pb . AuthorizeSessionArguments {
HostId : "hst_1234567890" ,
},
},
},
}},
2024-04-19 07:49:11 -07:00
errContains : `This field is required when 'attributes.authorize_session_arguments.host_id' is specified.` ,
2024-02-01 07:31:46 -08:00
},
2024-02-23 12:02:48 -05:00
{
name : "improperly formatted host id" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
Type : "target" ,
ScopeId : scope . Global . String (),
Value : "bad-host-id.alias" ,
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
Attrs : & pb . Alias_TargetAliasAttributes {
TargetAliasAttributes : & pb . TargetAliasAttributes {
AuthorizeSessionArguments : & pb . AuthorizeSessionArguments {
HostId : "badid_1234567890" ,
},
},
},
}},
errContains : `Incorrectly formatted identifier.` ,
},
2024-02-01 07:31:46 -08:00
{
name : "Alias to non existing target" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
ScopeId : scope . Global . String (),
Value : "unknowntarget.alias" ,
DestinationId : wrapperspb . String ( "ttcp_1234567890" ),
}},
errContains : `target with specified destination id "ttcp_1234567890" was not found` ,
},
{
name : "Duplicate Alias Value" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
ScopeId : scope . Global . String (),
Value : al . GetValue (),
}},
errContains : `alias value "test.duplicated.create" is already in use` ,
},
{
name : "Duplicate Alias Name" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
ScopeId : scope . Global . String (),
Value : "duplicate.alias.name" ,
Name : wrapperspb . String ( al . GetName ()),
}},
errContains : `name "alias name" is already in use` ,
},
{
name : "must be in global scope" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
ScopeId : p . GetPublicId (),
Value : "must.be.in.global.scope" ,
}},
errContains : `{name: "scope_id", desc: "This field is missing or improperly formatted."}` ,
},
{
name : "Can't specify Id" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
ScopeId : scope . Global . String (),
Id : globals . TargetAliasPrefix + "_notallowed" ,
}},
res : nil ,
errContains : "This is a read only field." ,
},
{
name : "Can't specify Created Time" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
ScopeId : scope . Global . String (),
CreatedTime : timestamppb . Now (),
}},
res : nil ,
errContains : "This is a read only field." ,
},
{
name : "Can't specify Update Time" ,
req : & pbs . CreateAliasRequest { Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
ScopeId : scope . Global . String (),
UpdatedTime : timestamppb . Now (),
}},
res : nil ,
errContains : "This is a read only field." ,
},
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
s , err := aliases . NewService ( context . Background (), repoFn , iamRepoFn , 1000 )
require . NoError ( err , "Error when getting new alias service." )
got , gErr := s . CreateAlias ( auth . DisabledAuthTestContext ( iamRepoFn , tc . req . GetItem (). GetScopeId ()), tc . req )
if tc . errContains != "" {
require . Error ( gErr )
assert . ErrorContains ( gErr , tc . errContains )
return
}
require . NoError ( gErr )
assert . Contains ( got . GetUri (), tc . res . Uri )
assert . True ( strings . HasPrefix ( got . GetItem (). GetId (), globals . TargetAliasPrefix + "_" ))
// 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
assert . Empty ( cmp . Diff (
got ,
tc . res ,
protocmp . Transform (),
cmpopts . SortSlices ( func ( a , b string ) bool {
return a < b
}),
), "CreateAlias(%q) got response %q, wanted %q" , tc . req , got , tc . res )
})
}
}
func TestUpdate ( t * testing . T ) {
ctx := context . Background ()
conn , _ := db . TestSetup ( t , "postgres" )
rw := db . New ( conn )
wrap := db . TestWrapper ( t )
kmsCache := kms . TestKms ( t , conn , wrap )
iamRepo := iam . TestRepo ( t , conn , wrap )
iamRepoFn := func () ( * iam . Repository , error ) {
return iamRepo , nil
}
_ , p := iam . TestScopes ( t , iamRepo )
tar := tcp . TestTarget ( ctx , t , conn , p . GetPublicId (), "testTarget" )
tar2 := tcp . TestTarget ( ctx , t , conn , p . GetPublicId (), "testTarget2" )
repoFn := func () ( * target . Repository , error ) {
return target . NewRepository ( ctx , rw , rw , kmsCache )
}
og := target . TestAlias ( t , rw , "default" ,
target . WithDestinationId ( tar . GetPublicId ()),
target . WithName ( "default" ),
target . WithDescription ( "default" ))
var ogVersion uint32 = 1
2024-02-29 14:42:26 -08:00
resetAlias := func ( version uint32 ) {
2024-02-01 07:31:46 -08:00
repo , err := repoFn ()
require . NoError ( t , err , "Couldn't get a new repo" )
og , _ , err = repo . UpdateAlias ( ctx , og , version , [] string { "Name" , "Description" , "DestinationId" , "Value" })
require . NoError ( t , err , "Failed to reset the alias" )
ogVersion = og . GetVersion ()
}
created := og . GetCreateTime (). GetTimestamp (). AsTime ()
toMerge := & pbs . UpdateAliasRequest {
Id : og . GetPublicId (),
}
globalScopeInfo := & scopes . ScopeInfo { Id : scope . Global . String (), Type : scope . Global . String (), Name : "global" , Description : "Global Scope" }
tested , err := aliases . NewService ( ctx , repoFn , iamRepoFn , 1000 )
require . NoError ( t , err , "Error creating new service" )
cases := [] struct {
name string
scopeId string
req * pbs . UpdateAliasRequest
res * pbs . UpdateAliasResponse
err error
}{
{
name : "Update an Existing Alias" ,
scopeId : og . GetScopeId (),
req : & pbs . UpdateAliasRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "name" , "description" },
},
Item : & pb . Alias {
Name : wrapperspb . String ( "updated" ),
Description : wrapperspb . String ( "updated" ),
},
},
res : & pbs . UpdateAliasResponse {
Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
Id : og . GetPublicId (),
ScopeId : og . GetScopeId (),
Scope : globalScopeInfo ,
Value : "default" ,
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
Name : wrapperspb . String ( "updated" ),
Description : wrapperspb . String ( "updated" ),
CreatedTime : og . GetCreateTime (). GetTimestamp (),
AuthorizedActions : testAuthorizedActions ,
},
},
},
{
name : "Multiple Paths in single string" ,
scopeId : og . GetScopeId (),
req : & pbs . UpdateAliasRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "name,description" },
},
Item : & pb . Alias {
Name : wrapperspb . String ( "updated" ),
Description : wrapperspb . String ( "updated" ),
},
},
res : & pbs . UpdateAliasResponse {
Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
Id : og . GetPublicId (),
ScopeId : og . GetScopeId (),
Scope : globalScopeInfo ,
Value : "default" ,
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
Name : wrapperspb . String ( "updated" ),
Description : wrapperspb . String ( "updated" ),
CreatedTime : og . GetCreateTime (). GetTimestamp (),
AuthorizedActions : testAuthorizedActions ,
},
},
},
{
name : "No Update Mask" ,
req : & pbs . UpdateAliasRequest {
Item : & pb . Alias {
Description : wrapperspb . String ( "updated desc" ),
},
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "No Paths in Mask" ,
scopeId : og . GetScopeId (),
req : & pbs . UpdateAliasRequest {
UpdateMask : & field_mask . FieldMask { Paths : [] string {}},
Item : & pb . Alias {
Description : wrapperspb . String ( "updated desc" ),
},
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
2024-02-29 14:57:38 -08:00
name : "Only non-existent paths in Mask" ,
2024-02-01 07:31:46 -08:00
scopeId : og . GetScopeId (),
req : & pbs . UpdateAliasRequest {
UpdateMask : & field_mask . FieldMask { Paths : [] string { "nonexistant_field" }},
Item : & pb . Alias {
Description : wrapperspb . String ( "updated desc" ),
},
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "Unset Name" ,
scopeId : og . GetScopeId (),
req : & pbs . UpdateAliasRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "name" },
},
Item : & pb . Alias {
Description : wrapperspb . String ( "ignored" ),
},
},
res : & pbs . UpdateAliasResponse {
Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
Id : og . GetPublicId (),
ScopeId : og . GetScopeId (),
Scope : globalScopeInfo ,
Value : "default" ,
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
Description : wrapperspb . String ( "default" ),
CreatedTime : og . GetCreateTime (). GetTimestamp (),
AuthorizedActions : testAuthorizedActions ,
},
},
},
{
name : "Update Only Name" ,
scopeId : og . GetScopeId (),
req : & pbs . UpdateAliasRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "name" },
},
Item : & pb . Alias {
Name : wrapperspb . String ( "updated" ),
Description : wrapperspb . String ( "ignored" ),
},
},
res : & pbs . UpdateAliasResponse {
Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
Id : og . GetPublicId (),
Name : wrapperspb . String ( "updated" ),
ScopeId : og . GetScopeId (),
Scope : globalScopeInfo ,
Value : "default" ,
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
Description : wrapperspb . String ( "default" ),
CreatedTime : og . GetCreateTime (). GetTimestamp (),
AuthorizedActions : testAuthorizedActions ,
},
},
},
{
name : "Update Only value" ,
scopeId : og . GetScopeId (),
req : & pbs . UpdateAliasRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "value" },
},
Item : & pb . Alias {
Name : wrapperspb . String ( "ignored" ),
Value : "updated" ,
},
},
res : & pbs . UpdateAliasResponse {
Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
Id : og . GetPublicId (),
ScopeId : og . GetScopeId (),
Scope : globalScopeInfo ,
Value : "updated" ,
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
Name : wrapperspb . String ( "default" ),
Description : wrapperspb . String ( "default" ),
CreatedTime : og . GetCreateTime (). GetTimestamp (),
AuthorizedActions : testAuthorizedActions ,
},
},
},
2024-04-19 07:49:11 -07:00
{
name : "Update destination id" ,
scopeId : og . GetScopeId (),
req : & pbs . UpdateAliasRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "destination_id" },
},
Item : & pb . Alias {
Name : wrapperspb . String ( "ignored" ),
DestinationId : wrapperspb . String ( "invalid format for targets" ),
},
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
2024-02-01 07:31:46 -08:00
{
name : "unset value" ,
scopeId : og . GetScopeId (),
req : & pbs . UpdateAliasRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "value" },
},
Item : & pb . Alias {
Name : wrapperspb . String ( "ignored" ),
},
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "Update Only destination id" ,
scopeId : og . GetScopeId (),
req : & pbs . UpdateAliasRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "destination_id" },
},
Item : & pb . Alias {
Value : "ignored" ,
DestinationId : wrapperspb . String ( tar2 . GetPublicId ()),
},
},
res : & pbs . UpdateAliasResponse {
Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
Id : og . GetPublicId (),
ScopeId : og . GetScopeId (),
Scope : globalScopeInfo ,
Value : "default" ,
DestinationId : wrapperspb . String ( tar2 . GetPublicId ()),
Name : wrapperspb . String ( "default" ),
Description : wrapperspb . String ( "default" ),
CreatedTime : og . GetCreateTime (). GetTimestamp (),
AuthorizedActions : testAuthorizedActions ,
},
},
},
{
name : "Unset destination id" ,
scopeId : og . GetScopeId (),
req : & pbs . UpdateAliasRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "destination_id" },
},
Item : & pb . Alias {
Value : "ignored" ,
},
},
res : & pbs . UpdateAliasResponse {
Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
Id : og . GetPublicId (),
ScopeId : og . GetScopeId (),
Scope : globalScopeInfo ,
Value : "default" ,
Name : wrapperspb . String ( "default" ),
Description : wrapperspb . String ( "default" ),
CreatedTime : og . GetCreateTime (). GetTimestamp (),
AuthorizedActions : testAuthorizedActions ,
},
},
},
{
name : "Update Only Description" ,
scopeId : og . GetScopeId (),
req : & pbs . UpdateAliasRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "description" },
},
Item : & pb . Alias {
Description : wrapperspb . String ( "updated" ),
},
},
res : & pbs . UpdateAliasResponse {
Item : & pb . Alias {
2024-02-02 14:33:32 -08:00
Type : "target" ,
2024-02-01 07:31:46 -08:00
Id : og . GetPublicId (),
ScopeId : og . GetScopeId (),
Scope : globalScopeInfo ,
Value : "default" ,
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
Name : wrapperspb . String ( "default" ),
Description : wrapperspb . String ( "updated" ),
CreatedTime : og . GetCreateTime (). GetTimestamp (),
AuthorizedActions : testAuthorizedActions ,
},
},
},
{
name : "Update a Non Existing Alias" ,
req : & pbs . UpdateAliasRequest {
Id : globals . TargetAliasPrefix + "_DoesntExis" ,
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "description" },
},
Item : & pb . Alias {
Description : wrapperspb . String ( "desc" ),
},
},
err : handlers . ApiErrorWithCode ( codes . NotFound ),
},
{
name : "Cant change Id" ,
req : & pbs . UpdateAliasRequest {
Id : og . GetPublicId (),
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "id" },
},
Item : & pb . Alias {
Id : globals . TargetAliasPrefix + "_somethinge" ,
Description : wrapperspb . String ( "new desc" ),
},
},
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
2024-02-23 12:02:48 -05:00
{
name : "Cant use invalid host id" ,
req : & pbs . UpdateAliasRequest {
Id : og . GetPublicId (),
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "host_id" },
},
Item : & pb . Alias {
Description : wrapperspb . String ( "new desc" ),
Attrs : & pb . Alias_TargetAliasAttributes {
& pb . TargetAliasAttributes {
AuthorizeSessionArguments : & pb . AuthorizeSessionArguments {
HostId : "badid_1234567890" ,
},
},
},
},
},
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "Update with static host id" ,
req : & pbs . UpdateAliasRequest {
Id : og . GetPublicId (),
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "attributes.authorize_session_arguments.host_id" },
},
Item : & pb . Alias {
Description : wrapperspb . String ( "new desc" ),
Attrs : & pb . Alias_TargetAliasAttributes {
& pb . TargetAliasAttributes {
AuthorizeSessionArguments : & pb . AuthorizeSessionArguments {
HostId : "hst_1234567890" ,
},
},
},
},
},
res : & pbs . UpdateAliasResponse {
Item : & pb . Alias {
Type : "target" ,
Id : og . GetPublicId (),
Name : wrapperspb . String ( "default" ),
ScopeId : og . GetScopeId (),
Scope : globalScopeInfo ,
Value : "default" ,
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
Description : wrapperspb . String ( "default" ),
CreatedTime : og . GetCreateTime (). GetTimestamp (),
AuthorizedActions : testAuthorizedActions ,
Attrs : & pb . Alias_TargetAliasAttributes {
& pb . TargetAliasAttributes {
AuthorizeSessionArguments : & pb . AuthorizeSessionArguments {
HostId : "hst_1234567890" ,
},
},
},
},
},
},
{
name : "Update with dynamic host id" ,
req : & pbs . UpdateAliasRequest {
Id : og . GetPublicId (),
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "attributes.authorize_session_arguments.host_id" },
},
Item : & pb . Alias {
Description : wrapperspb . String ( "new desc" ),
Attrs : & pb . Alias_TargetAliasAttributes {
& pb . TargetAliasAttributes {
AuthorizeSessionArguments : & pb . AuthorizeSessionArguments {
HostId : "hplg_1234567890" ,
},
},
},
},
},
res : & pbs . UpdateAliasResponse {
Item : & pb . Alias {
Type : "target" ,
Id : og . GetPublicId (),
Name : wrapperspb . String ( "default" ),
ScopeId : og . GetScopeId (),
Scope : globalScopeInfo ,
Value : "default" ,
DestinationId : wrapperspb . String ( tar . GetPublicId ()),
Description : wrapperspb . String ( "default" ),
CreatedTime : og . GetCreateTime (). GetTimestamp (),
AuthorizedActions : testAuthorizedActions ,
Attrs : & pb . Alias_TargetAliasAttributes {
& pb . TargetAliasAttributes {
AuthorizeSessionArguments : & pb . AuthorizeSessionArguments {
HostId : "hplg_1234567890" ,
},
},
},
},
},
},
2024-02-01 07:31:46 -08:00
{
name : "Cant specify Created Time" ,
req : & pbs . UpdateAliasRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "created_time" },
},
Item : & pb . Alias {
CreatedTime : timestamppb . Now (),
},
},
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "Cant specify Updated Time" ,
req : & pbs . UpdateAliasRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "updated_time" },
},
Item : & pb . Alias {
UpdatedTime : timestamppb . Now (),
},
},
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
ver := ogVersion
tc . req . Item . Version = ver
assert , require := assert . New ( t ), require . New ( t )
req := proto . Clone ( toMerge ).( * pbs . UpdateAliasRequest )
proto . Merge ( req , tc . req )
// Test with bad version (too high, too low)
req . Item . Version = ver + 2
_ , gErr := tested . UpdateAlias ( auth . DisabledAuthTestContext ( iamRepoFn , tc . scopeId ), req )
require . Error ( gErr )
req . Item . Version = ver - 1
_ , gErr = tested . UpdateAlias ( auth . DisabledAuthTestContext ( iamRepoFn , tc . scopeId ), req )
require . Error ( gErr )
req . Item . Version = ver
got , gErr := tested . UpdateAlias ( auth . DisabledAuthTestContext ( iamRepoFn , tc . scopeId ), req )
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "UpdateAlias(%+v) got error %v, wanted %v" , req , gErr , tc . err )
return
}
require . NoError ( gErr )
2024-02-29 14:42:26 -08:00
defer resetAlias ( got . GetItem (). GetVersion ())
2024-02-01 07:31:46 -08:00
assert . NotNilf ( tc . res , "Expected UpdateAlias response to be nil, but was %v" , got )
gotUpdateTime := got . GetItem (). GetUpdatedTime (). AsTime ()
// Verify it is a alias updated after it was created
assert . True ( gotUpdateTime . After ( created ), "Updated alias should have been updated after it's creation. Was updated %v, which is after %v" , gotUpdateTime , created )
// Clear all values which are hard to compare against.
got . Item . UpdatedTime , tc . res . Item . UpdatedTime = nil , nil
assert . Equal ( ver + 1 , got . GetItem (). GetVersion ())
tc . res . Item . Version = ver + 1
assert . Empty ( cmp . Diff (
got ,
tc . res ,
protocmp . Transform (),
cmpopts . SortSlices ( func ( a , b string ) bool {
return a < b
}),
), "UpdateAlias(%q) got response %q, wanted %q" , req , got , tc . res )
})
}
}