mirror of https://github.com/hashicorp/boundary
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.
887 lines
31 KiB
887 lines
31 KiB
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package targets_test
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/boundary/api"
|
|
"github.com/hashicorp/boundary/api/aliases"
|
|
"github.com/hashicorp/boundary/api/credentiallibraries"
|
|
"github.com/hashicorp/boundary/api/credentials"
|
|
"github.com/hashicorp/boundary/api/credentialstores"
|
|
"github.com/hashicorp/boundary/api/hostcatalogs"
|
|
"github.com/hashicorp/boundary/api/hosts"
|
|
"github.com/hashicorp/boundary/api/hostsets"
|
|
"github.com/hashicorp/boundary/api/roles"
|
|
"github.com/hashicorp/boundary/api/targets"
|
|
"github.com/hashicorp/boundary/globals"
|
|
aliastar "github.com/hashicorp/boundary/internal/alias/target"
|
|
"github.com/hashicorp/boundary/internal/credential/vault"
|
|
"github.com/hashicorp/boundary/internal/daemon/controller"
|
|
"github.com/hashicorp/boundary/internal/daemon/worker"
|
|
"github.com/hashicorp/boundary/internal/db"
|
|
"github.com/hashicorp/boundary/internal/iam"
|
|
"github.com/hashicorp/boundary/internal/tests/helper"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
_ "github.com/hashicorp/boundary/internal/daemon/controller/handlers/targets/tcp"
|
|
)
|
|
|
|
func TestHostSetASD(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
|
|
token := tc.Token()
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
client := tc.Client().Clone()
|
|
client.SetToken(token.Token)
|
|
|
|
hc, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
|
require.NoError(err)
|
|
|
|
hSetClient := hostsets.NewClient(client)
|
|
hSet, err := hSetClient.Create(tc.Context(), hc.Item.Id)
|
|
require.NoError(err)
|
|
require.NotNil(hSet)
|
|
hSet2, err := hSetClient.Create(tc.Context(), hc.Item.Id)
|
|
require.NoError(err)
|
|
require.NotNil(hSet2)
|
|
|
|
tarClient := targets.NewClient(client)
|
|
tar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("foo"), targets.WithTcpTargetDefaultPort(2))
|
|
require.NoError(err)
|
|
require.NotNil(tar)
|
|
assert.Empty(tar.Item.HostSourceIds)
|
|
|
|
aliasedTar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("aliased"), targets.WithTcpTargetDefaultPort(2))
|
|
require.NoError(err)
|
|
require.NotNil(aliasedTar)
|
|
assert.Empty(aliasedTar.Item.HostSourceIds)
|
|
|
|
rw := db.New(tc.DbConn())
|
|
al := aliastar.TestAlias(t, rw, "alias.value", aliastar.WithDestinationId(aliasedTar.Item.Id))
|
|
|
|
cases := []struct {
|
|
name string
|
|
id string
|
|
}{
|
|
{
|
|
name: "target id",
|
|
id: tar.Item.Id,
|
|
},
|
|
{
|
|
name: "aliases",
|
|
id: al.GetValue(),
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
tar, err := tarClient.AddHostSources(tc.Context(), c.id, 1, []string{hSet.Item.Id})
|
|
require.NoError(err)
|
|
require.NotNil(tar)
|
|
assert.ElementsMatch(tar.Item.HostSourceIds, []string{hSet.Item.Id})
|
|
|
|
tar, err = tarClient.SetHostSources(tc.Context(), c.id, tar.Item.Version, []string{hSet2.Item.Id})
|
|
require.NoError(err)
|
|
require.NotNil(tar)
|
|
assert.ElementsMatch(tar.Item.HostSourceIds, []string{hSet2.Item.Id})
|
|
|
|
tar, err = tarClient.RemoveHostSources(tc.Context(), c.id, tar.Item.Version, []string{hSet2.Item.Id})
|
|
require.NoError(err)
|
|
require.NotNil(tar)
|
|
assert.Empty(tar.Item.HostSourceIds)
|
|
}
|
|
}
|
|
|
|
func TestCredentialSourcesASD(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
vaultServ := vault.NewTestVaultServer(t, vault.WithTestVaultTLS(vault.TestNoTLS))
|
|
_, vaultTok := vaultServ.CreateToken(t)
|
|
|
|
token := tc.Token()
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
client := tc.Client().Clone()
|
|
client.SetToken(token.Token)
|
|
|
|
csVault, err := credentialstores.NewClient(client).Create(tc.Context(), "vault", proj.GetPublicId(),
|
|
credentialstores.WithVaultCredentialStoreAddress(vaultServ.Addr), credentialstores.WithVaultCredentialStoreToken(vaultTok))
|
|
require.NoError(err)
|
|
require.NotNil(csVault)
|
|
|
|
lClient := credentiallibraries.NewClient(client)
|
|
lib1, err := lClient.Create(tc.Context(), "vault-generic", csVault.Item.Id, credentiallibraries.WithVaultCredentialLibraryPath("something1"))
|
|
require.NoError(err)
|
|
require.NotNil(lib1)
|
|
|
|
lib2, err := lClient.Create(tc.Context(), "vault-generic", csVault.Item.Id, credentiallibraries.WithVaultCredentialLibraryPath("something2"))
|
|
require.NoError(err)
|
|
require.NotNil(lib2)
|
|
|
|
csStatic, err := credentialstores.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
|
require.NoError(err)
|
|
require.NotNil(csStatic)
|
|
|
|
cClient := credentials.NewClient(client)
|
|
cOpts := []credentials.Option{credentials.WithUsernamePasswordCredentialUsername("user"), credentials.WithUsernamePasswordCredentialPassword("pass")}
|
|
cred, err := cClient.Create(tc.Context(), "username_password", csStatic.Item.Id, cOpts...)
|
|
require.NoError(err)
|
|
require.NotNil(cred)
|
|
|
|
tarClient := targets.NewClient(client)
|
|
tar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("foo"), targets.WithTcpTargetDefaultPort(2))
|
|
require.NoError(err)
|
|
require.NotNil(tar)
|
|
assert.Empty(tar.Item.BrokeredCredentialSourceIds)
|
|
|
|
aliasedTar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("aliased"), targets.WithTcpTargetDefaultPort(2))
|
|
require.NoError(err)
|
|
require.NotNil(aliasedTar)
|
|
assert.Empty(aliasedTar.Item.BrokeredCredentialSourceIds)
|
|
|
|
rw := db.New(tc.DbConn())
|
|
al := aliastar.TestAlias(t, rw, "alias.value", aliastar.WithDestinationId(aliasedTar.Item.Id))
|
|
|
|
cases := []struct {
|
|
name string
|
|
id string
|
|
}{
|
|
{
|
|
name: "target id",
|
|
id: tar.Item.Id,
|
|
},
|
|
{
|
|
name: "aliases",
|
|
id: al.GetValue(),
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
// Add first Vault library
|
|
tar, err := tarClient.AddCredentialSources(tc.Context(), c.id, 1,
|
|
targets.WithBrokeredCredentialSourceIds([]string{lib1.Item.Id}))
|
|
require.NoError(err)
|
|
require.NotNil(tar)
|
|
assert.ElementsMatch(tar.Item.BrokeredCredentialSourceIds, []string{lib1.Item.Id})
|
|
assert.ElementsMatch(tar.Item.BrokeredCredentialSources, []*targets.CredentialSource{
|
|
{
|
|
Id: lib1.Item.Id,
|
|
CredentialStoreId: csVault.Item.Id,
|
|
},
|
|
})
|
|
|
|
// Set second Vault library and a static credential
|
|
tar, err = tarClient.SetCredentialSources(tc.Context(), c.id, tar.Item.Version,
|
|
targets.WithBrokeredCredentialSourceIds([]string{lib2.Item.Id, cred.Item.Id}))
|
|
require.NoError(err)
|
|
require.NotNil(tar)
|
|
assert.ElementsMatch(tar.Item.BrokeredCredentialSourceIds, []string{lib2.Item.Id, cred.Item.Id})
|
|
assert.ElementsMatch(tar.Item.BrokeredCredentialSources, []*targets.CredentialSource{
|
|
{
|
|
Id: lib2.Item.Id,
|
|
CredentialStoreId: csVault.Item.Id,
|
|
},
|
|
{
|
|
Id: cred.Item.Id,
|
|
CredentialStoreId: csStatic.Item.Id,
|
|
},
|
|
})
|
|
// Remove second Vault library
|
|
tar, err = tarClient.RemoveCredentialSources(tc.Context(), c.id, tar.Item.Version,
|
|
targets.WithBrokeredCredentialSourceIds([]string{lib2.Item.Id}))
|
|
require.NoError(err)
|
|
require.NotNil(tar)
|
|
assert.ElementsMatch(tar.Item.BrokeredCredentialSourceIds, []string{cred.Item.Id})
|
|
assert.ElementsMatch(tar.Item.BrokeredCredentialSources, []*targets.CredentialSource{
|
|
{
|
|
Id: cred.Item.Id,
|
|
CredentialStoreId: csStatic.Item.Id,
|
|
},
|
|
})
|
|
|
|
// Set empty credential sources
|
|
tar, err = tarClient.SetCredentialSources(tc.Context(), c.id, tar.Item.Version,
|
|
targets.WithBrokeredCredentialSourceIds([]string{}))
|
|
require.NoError(err)
|
|
require.NotNil(tar)
|
|
assert.Empty(tar.Item.BrokeredCredentialSourceIds)
|
|
}
|
|
}
|
|
|
|
func TestList(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
|
|
// Add unpriv user to default role in new project. Also add create grant as
|
|
// it will be needed later in the test and no-op for listing visibility.
|
|
rls, err := roles.NewClient(client).List(tc.Context(), proj.GetPublicId())
|
|
require.NoError(err)
|
|
var defaultRoleId string
|
|
for _, rl := range rls.Items {
|
|
if strings.Contains(rl.Name, "Default") {
|
|
defaultRoleId = rl.Id
|
|
break
|
|
}
|
|
}
|
|
require.NotEmpty(defaultRoleId)
|
|
unprivToken := tc.UnprivilegedToken()
|
|
iam.TestUserRole(t, tc.DbConn(), defaultRoleId, unprivToken.UserId)
|
|
iam.TestRoleGrant(t, tc.DbConn(), defaultRoleId, "type=target;actions=create")
|
|
iam.TestRoleGrant(t, tc.DbConn(), defaultRoleId, "ids=*;type=target;actions=no-op")
|
|
|
|
client.SetToken(unprivToken.Token)
|
|
tarClient := targets.NewClient(client)
|
|
ul, err := tarClient.List(tc.Context(), proj.GetPublicId())
|
|
require.NoError(err)
|
|
assert.Empty(ul.Items)
|
|
|
|
var expected []*targets.Target
|
|
for i := 0; i < 10; i++ {
|
|
expected = append(expected, &targets.Target{Name: fmt.Sprint(i)})
|
|
}
|
|
|
|
tcr, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName(expected[0].Name), targets.WithTcpTargetDefaultPort(2))
|
|
require.NoError(err)
|
|
expected[0] = tcr.Item
|
|
|
|
ul, err = tarClient.List(tc.Context(), proj.GetPublicId())
|
|
require.NoError(err)
|
|
assert.ElementsMatch(comparableSlice(expected[:1]), comparableSlice(ul.Items))
|
|
|
|
for i := 1; i < 10; i++ {
|
|
tcr, err = tarClient.Create(
|
|
tc.Context(),
|
|
"tcp",
|
|
proj.GetPublicId(),
|
|
targets.WithName(expected[i].Name),
|
|
targets.WithTcpTargetDefaultPort(uint32(i)),
|
|
targets.WithTcpTargetDefaultClientPort(uint32(i+100)),
|
|
)
|
|
require.NoError(err)
|
|
expected[i] = tcr.Item
|
|
}
|
|
filterItem := expected[3]
|
|
ul, err = tarClient.List(tc.Context(), proj.GetPublicId())
|
|
require.NoError(err)
|
|
assert.ElementsMatch(comparableSlice(expected), comparableSlice(ul.Items))
|
|
|
|
ul, err = tarClient.List(tc.Context(), proj.GetPublicId(),
|
|
targets.WithFilter(fmt.Sprintf(`"/item/id"==%q`, filterItem.Id)))
|
|
require.NoError(err)
|
|
assert.Len(ul.Items, 1)
|
|
assert.Equal(filterItem.Id, ul.Items[0].Id)
|
|
|
|
filterstr := fmt.Sprintf(`"/item/attributes/default_port"==%d`, uint32(filterItem.Attributes["default_port"].(float64)))
|
|
ul, err = tarClient.List(tc.Context(), proj.GetPublicId(),
|
|
targets.WithFilter(filterstr))
|
|
require.NoError(err)
|
|
assert.Len(ul.Items, 1)
|
|
assert.Equal(filterItem.Id, ul.Items[0].Id)
|
|
}
|
|
|
|
func TestListWithListToken(t *testing.T) {
|
|
// Set database read timeout to avoid duplicates in response
|
|
oldReadTimeout := globals.RefreshReadLookbackDuration
|
|
globals.RefreshReadLookbackDuration = 0
|
|
t.Cleanup(func() {
|
|
globals.RefreshReadLookbackDuration = oldReadTimeout
|
|
})
|
|
require := require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
|
|
tarClient := targets.NewClient(client)
|
|
_, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("1"), targets.WithTcpTargetDefaultPort(2))
|
|
require.NoError(err)
|
|
_, err = tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("2"), targets.WithTcpTargetDefaultPort(2))
|
|
require.NoError(err)
|
|
|
|
// Refresh tokens using project scope
|
|
res, err := tarClient.List(tc.Context(), proj.GetPublicId(), targets.WithRecursive(true))
|
|
require.NoError(err)
|
|
require.Len(res.Items, 2, "expected the 2 targets created above")
|
|
refTok := res.ListToken
|
|
|
|
res, err = tarClient.List(tc.Context(), proj.GetPublicId(), targets.WithRecursive(true), targets.WithListToken(refTok))
|
|
require.NoError(err)
|
|
require.Empty(res.Items)
|
|
|
|
// Refresh tokens recursive listing over global scope
|
|
res, err = tarClient.List(tc.Context(), "global", targets.WithRecursive(true))
|
|
require.NoError(err)
|
|
require.Len(res.Items, 4, "expected the 2 targets created above and the 2 auto created for the test controller")
|
|
refTok = res.ListToken
|
|
|
|
res, err = tarClient.List(tc.Context(), "global", targets.WithRecursive(true), targets.WithListToken(refTok))
|
|
require.NoError(err)
|
|
require.Empty(res.Items)
|
|
}
|
|
|
|
func TestListWithPageSize(t *testing.T) {
|
|
// Set database read timeout to avoid duplicates in response
|
|
oldReadTimeout := globals.RefreshReadLookbackDuration
|
|
globals.RefreshReadLookbackDuration = 0
|
|
t.Cleanup(func() {
|
|
globals.RefreshReadLookbackDuration = oldReadTimeout
|
|
})
|
|
require := require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
|
|
tarClient := targets.NewClient(client)
|
|
_, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("1"), targets.WithTcpTargetDefaultPort(2))
|
|
require.NoError(err)
|
|
_, err = tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("2"), targets.WithTcpTargetDefaultPort(2))
|
|
require.NoError(err)
|
|
|
|
// Refresh tokens recursive listing over global scope
|
|
res, err := tarClient.List(tc.Context(), "global", targets.WithRecursive(true), targets.WithPageSize(2))
|
|
require.NoError(err)
|
|
require.Len(res.Items, 4, "expected the 2 targets created above and the 2 auto created for the test controller")
|
|
refTok := res.ListToken
|
|
|
|
res, err = tarClient.List(tc.Context(), "global", targets.WithRecursive(true), targets.WithListToken(refTok))
|
|
require.NoError(err)
|
|
require.Empty(res.Items)
|
|
}
|
|
|
|
func TestTarget_AddressMutualExclusiveRelationship(t *testing.T) {
|
|
tc := controller.NewTestController(t, nil)
|
|
|
|
client := tc.Client()
|
|
at := tc.Token()
|
|
client.SetToken(at.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(at.UserId))
|
|
tClient := targets.NewClient(client)
|
|
|
|
// Create target with a network address association
|
|
targetResp, err := tClient.Create(tc.Context(), "tcp", proj.GetPublicId(),
|
|
targets.WithName("test-address"), targets.WithAddress("[::1]"), targets.WithTcpTargetDefaultPort(22))
|
|
require.NoError(t, err)
|
|
require.NotNil(t, targetResp)
|
|
require.Equal(t, "::1", targetResp.GetItem().Address)
|
|
|
|
// Setup host catalog, host set, & host resources
|
|
hc, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
|
require.NoError(t, err)
|
|
require.NotNil(t, hc)
|
|
hs, err := hostsets.NewClient(client).Create(tc.Context(), hc.Item.Id)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, hs)
|
|
h, err := hosts.NewClient(client).Create(tc.Context(), hc.Item.Id, hosts.WithStaticHostAddress("[::1]"))
|
|
require.NoError(t, err)
|
|
require.NotNil(t, h)
|
|
hUpdate, err := hostsets.NewClient(client).AddHosts(tc.Context(), hs.Item.Id, hs.Item.Version, []string{h.GetItem().Id})
|
|
require.NoError(t, err)
|
|
require.NotNil(t, hUpdate)
|
|
|
|
// Expect error when associating a host source to the target with a direct network address association
|
|
targetId := targetResp.GetItem().Id
|
|
version := targetResp.GetItem().Version
|
|
updateResp, err := tClient.AddHostSources(tc.Context(), targetId, version, []string{hs.Item.Id})
|
|
require.Error(t, err)
|
|
require.Nil(t, updateResp)
|
|
apiErr := api.AsServerError(err)
|
|
require.NotNil(t, apiErr)
|
|
require.Equal(t, http.StatusBadRequest, apiErr.Response().StatusCode())
|
|
|
|
// Remove direct network address association. Successfully add a host source to target.
|
|
targetResp, err = tClient.Update(tc.Context(), targetId, version, targets.DefaultAddress())
|
|
require.NoError(t, err)
|
|
require.NotNil(t, targetResp)
|
|
require.Empty(t, targetResp.GetItem().Address)
|
|
version = targetResp.GetItem().Version
|
|
updateResp, err = tClient.AddHostSources(tc.Context(), targetId, version, []string{hs.Item.Id})
|
|
require.NoError(t, err)
|
|
require.NotNil(t, updateResp)
|
|
require.Empty(t, updateResp.GetItem().Address)
|
|
require.Equal(t, []string{hs.Item.Id}, updateResp.GetItem().HostSourceIds)
|
|
}
|
|
|
|
func TestTarget_HostSourceMutualExclusiveRelationship(t *testing.T) {
|
|
tc := controller.NewTestController(t, nil)
|
|
|
|
client := tc.Client()
|
|
at := tc.Token()
|
|
client.SetToken(at.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(at.UserId))
|
|
tClient := targets.NewClient(client)
|
|
|
|
// Setup host catalog, host set, & host resources
|
|
hc, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
|
require.NoError(t, err)
|
|
require.NotNil(t, hc)
|
|
hs, err := hostsets.NewClient(client).Create(tc.Context(), hc.Item.Id)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, hs)
|
|
h, err := hosts.NewClient(client).Create(tc.Context(), hc.Item.Id, hosts.WithStaticHostAddress("[::1]"))
|
|
require.NoError(t, err)
|
|
require.NotNil(t, h)
|
|
hUpdate, err := hostsets.NewClient(client).AddHosts(tc.Context(), hs.Item.Id, hs.Item.Version, []string{h.GetItem().Id})
|
|
require.NoError(t, err)
|
|
require.NotNil(t, hUpdate)
|
|
|
|
// Create target without a network address association
|
|
targetResp, err := tClient.Create(tc.Context(), "tcp", proj.GetPublicId(),
|
|
targets.WithName("test-host-source"), targets.WithTcpTargetDefaultPort(22))
|
|
require.NoError(t, err)
|
|
require.NotNil(t, targetResp)
|
|
require.Empty(t, targetResp.GetItem().Address)
|
|
|
|
// Expect error when associating a address to the target with a host source association
|
|
targetId := targetResp.GetItem().Id
|
|
version := targetResp.GetItem().Version
|
|
updateResp, err := tClient.AddHostSources(tc.Context(), targetId, version, []string{hs.Item.Id})
|
|
require.NoError(t, err)
|
|
require.NotNil(t, updateResp)
|
|
require.Empty(t, updateResp.GetItem().Address)
|
|
require.Equal(t, []string{hs.Item.Id}, updateResp.GetItem().HostSourceIds)
|
|
version = updateResp.GetItem().Version
|
|
updateResp, err = tClient.Update(tc.Context(), targetId, version, targets.WithAddress("[::1]"))
|
|
require.Error(t, err)
|
|
require.Nil(t, updateResp)
|
|
apiErr := api.AsServerError(err)
|
|
require.NotNil(t, apiErr)
|
|
require.Equal(t, http.StatusBadRequest, apiErr.Response().StatusCode())
|
|
|
|
// Remove host source association. Successfully assign a network address to the target.
|
|
updateResp, err = tClient.RemoveHostSources(tc.Context(), targetId, version, []string{hs.Item.Id})
|
|
require.NoError(t, err)
|
|
require.NotNil(t, updateResp)
|
|
require.Empty(t, updateResp.GetItem().HostSourceIds)
|
|
version = updateResp.GetItem().Version
|
|
updateResp, err = tClient.Update(tc.Context(), targetId, version, targets.WithAddress("[::1]"))
|
|
require.NoError(t, err)
|
|
require.NotNil(t, updateResp)
|
|
require.Equal(t, "::1", updateResp.GetItem().Address)
|
|
require.Empty(t, updateResp.GetItem().HostSourceIds)
|
|
}
|
|
|
|
func TestCreateTarget_DirectlyAttachedAddress(t *testing.T) {
|
|
tc := controller.NewTestController(t, nil)
|
|
|
|
client := tc.Client()
|
|
at := tc.Token()
|
|
client.SetToken(at.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(at.UserId))
|
|
tClient := targets.NewClient(client)
|
|
|
|
tests := []struct {
|
|
name string
|
|
address string
|
|
expectedAddress string
|
|
}{
|
|
{
|
|
name: "target-ipv4-address",
|
|
address: "127.0.0.1",
|
|
expectedAddress: "127.0.0.1",
|
|
},
|
|
{
|
|
name: "target-ipv6-address",
|
|
address: "[2001:4860:4860:0:0:0:0:8888]",
|
|
expectedAddress: "2001:4860:4860:0:0:0:0:8888",
|
|
},
|
|
{
|
|
name: "target-abbreviated-ipv6-address",
|
|
address: "[2001:4860:4860::8888]",
|
|
expectedAddress: "2001:4860:4860::8888",
|
|
},
|
|
{
|
|
name: "target-dns-address",
|
|
address: "www.google.com",
|
|
expectedAddress: "www.google.com",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
createResp, err := tClient.Create(tc.Context(), "tcp", proj.PublicId,
|
|
targets.WithName(tt.name), targets.WithAddress(tt.address), targets.WithTcpTargetDefaultPort(22))
|
|
require.NoError(err)
|
|
require.NotNil(createResp)
|
|
assert.Equal(tt.expectedAddress, createResp.GetItem().Address)
|
|
|
|
targetId := createResp.GetItem().Id
|
|
version := createResp.GetItem().Version
|
|
readResp, err := tClient.Read(tc.Context(), targetId)
|
|
require.NoError(err)
|
|
require.NotNil(readResp)
|
|
assert.Equal(tt.expectedAddress, readResp.GetItem().Address)
|
|
|
|
updateResp, err := tClient.Update(tc.Context(), targetId, version, targets.DefaultAddress())
|
|
require.NoError(err)
|
|
require.NotNil(updateResp)
|
|
assert.Empty(updateResp.GetItem().Address)
|
|
|
|
readResp, err = tClient.Read(tc.Context(), targetId)
|
|
require.NoError(err)
|
|
require.NotNil(readResp)
|
|
assert.Empty(readResp.GetItem().Address)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUpdateTarget_DeleteAddress(t *testing.T) {
|
|
tc := controller.NewTestController(t, nil)
|
|
|
|
client := tc.Client()
|
|
at := tc.Token()
|
|
client.SetToken(at.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(at.UserId))
|
|
tClient := targets.NewClient(client)
|
|
|
|
assert, require := assert.New(t), require.New(t)
|
|
|
|
// Create Target with address
|
|
addr := "127.0.0.1"
|
|
createResp, err := tClient.Create(tc.Context(), "tcp", proj.PublicId,
|
|
targets.WithName("test_target_addr_delete"), targets.WithAddress(addr), targets.WithTcpTargetDefaultPort(22))
|
|
require.NoError(err)
|
|
require.NotNil(createResp)
|
|
assert.Equal(addr, createResp.GetItem().Address)
|
|
|
|
aliasedTar, err := tClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("aliased"), targets.WithTcpTargetDefaultPort(2))
|
|
require.NoError(err)
|
|
require.NotNil(aliasedTar)
|
|
|
|
rw := db.New(tc.DbConn())
|
|
al := aliastar.TestAlias(t, rw, "alias.value", aliastar.WithDestinationId(aliasedTar.Item.Id))
|
|
|
|
cases := []struct {
|
|
name string
|
|
id string
|
|
}{
|
|
{
|
|
name: "target id",
|
|
id: createResp.Item.Id,
|
|
},
|
|
{
|
|
name: "aliases",
|
|
id: al.GetValue(),
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
// Update to delete address (set to null)
|
|
updateResp, err := tClient.Update(tc.Context(), c.id, 1, targets.DefaultAddress())
|
|
require.NoError(err)
|
|
require.NotNil(updateResp)
|
|
assert.Empty(updateResp.GetItem().Address)
|
|
|
|
// Do it again with same version, should error
|
|
_, err = tClient.Update(tc.Context(), c.id, 1, targets.DefaultAddress())
|
|
require.Error(err)
|
|
|
|
// Do it again with the correct version, ensure this is not an error.
|
|
secondUpdateResp, err := tClient.Update(tc.Context(), c.id, updateResp.Item.Version, targets.DefaultAddress())
|
|
require.NoError(err)
|
|
require.NotNil(secondUpdateResp)
|
|
assert.Empty(secondUpdateResp.GetItem().Address)
|
|
|
|
assert.NotEqual(updateResp.Item.Version, secondUpdateResp.Item.Version)
|
|
}
|
|
}
|
|
|
|
func comparableSlice(in []*targets.Target) []targets.Target {
|
|
var filtered []targets.Target
|
|
for _, i := range in {
|
|
p := targets.Target{
|
|
Id: i.Id,
|
|
Name: i.Name,
|
|
Description: i.Description,
|
|
CreatedTime: i.CreatedTime,
|
|
UpdatedTime: i.UpdatedTime,
|
|
}
|
|
filtered = append(filtered, p)
|
|
}
|
|
return filtered
|
|
}
|
|
|
|
func TestCreateWithAliases(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
|
|
tarClient := targets.NewClient(client)
|
|
|
|
hostId := "hst_1234567890"
|
|
|
|
tar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("foo"), targets.WithTcpTargetDefaultPort(2), targets.WithAliases([]targets.Alias{
|
|
{
|
|
Value: "alias1",
|
|
ScopeId: "global",
|
|
Attributes: &targets.TargetAliasAttributes{
|
|
AuthorizeSessionArguments: &targets.AuthorizeSessionArguments{
|
|
HostId: hostId,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Value: "alias2",
|
|
ScopeId: "global",
|
|
},
|
|
}))
|
|
require.NoError(err)
|
|
assert.NotNil(tar)
|
|
assert.Len(tar.GetItem().Aliases, 2)
|
|
assert.NotEmpty(tar.GetItem().Aliases[0].Id)
|
|
assert.NotEmpty(tar.GetItem().Aliases[1].Id)
|
|
assert.NotEqual(tar.GetItem().Aliases[0].Value, tar.GetItem().Aliases[1].Value)
|
|
|
|
aliasClient := aliases.NewClient(client)
|
|
a1, err := aliasClient.Read(tc.Context(), tar.GetItem().Aliases[0].Id)
|
|
require.NoError(err)
|
|
assert.Equal("alias1", a1.Item.Value)
|
|
}
|
|
|
|
func TestCrud(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
|
|
checkResource := func(t *testing.T, step string, h *targets.Target, err error, wantedName string, wantVersion uint32) {
|
|
t.Helper()
|
|
require.NoError(err, step)
|
|
assert.NotNil(h, "returned no resource", step)
|
|
gotName := ""
|
|
if h.Name != "" {
|
|
gotName = h.Name
|
|
}
|
|
assert.Equal(wantedName, gotName, step)
|
|
assert.Equal(wantVersion, h.Version)
|
|
}
|
|
|
|
tarClient := targets.NewClient(client)
|
|
|
|
tar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("foo"), targets.WithTcpTargetDefaultPort(2))
|
|
checkResource(t, "create", tar.Item, err, "foo", 1)
|
|
|
|
aliasedTar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("aliased"), targets.WithTcpTargetDefaultPort(2))
|
|
checkResource(t, "create", aliasedTar.Item, err, "aliased", 1)
|
|
|
|
rw := db.New(tc.DbConn())
|
|
al := aliastar.TestAlias(t, rw, "alias.value", aliastar.WithDestinationId(aliasedTar.Item.Id))
|
|
|
|
cases := []struct {
|
|
name string
|
|
id string
|
|
initialName string
|
|
}{
|
|
{
|
|
name: "target id",
|
|
id: tar.Item.Id,
|
|
initialName: "foo",
|
|
},
|
|
{
|
|
name: "aliases",
|
|
id: al.GetValue(),
|
|
initialName: "aliased",
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
tar, err := tarClient.Read(tc.Context(), c.id)
|
|
checkResource(t, "read", tar.Item, err, c.initialName, 1)
|
|
|
|
tar, err = tarClient.Update(tc.Context(), c.id, tar.Item.Version, targets.WithName("bar"))
|
|
checkResource(t, "update", tar.Item, err, "bar", 2)
|
|
|
|
_, err = tarClient.Delete(tc.Context(), c.id)
|
|
assert.NoError(err)
|
|
}
|
|
|
|
t.Run("deleting unknown target is not found", func(t *testing.T) {
|
|
_, err = tarClient.Delete(tc.Context(), tar.Item.Id)
|
|
assert.Error(err)
|
|
apiErr := api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
|
})
|
|
|
|
t.Run("deleting unknown alias is not found", func(t *testing.T) {
|
|
_, err = tarClient.Delete(tc.Context(), al.GetValue())
|
|
assert.Error(err)
|
|
apiErr := api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
|
})
|
|
}
|
|
|
|
func TestSet_Errors(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
|
|
tarClient := targets.NewClient(client)
|
|
|
|
tar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("foo"), targets.WithTcpTargetDefaultPort(2))
|
|
require.NoError(err)
|
|
assert.NotNil(tar)
|
|
validTargetId := tar.GetItem().Id
|
|
|
|
// A malformed id is processed as the id and not a different path to the api.
|
|
_, err = tarClient.Read(tc.Context(), fmt.Sprintf("%s/../", tar.Item.Id))
|
|
require.Error(err)
|
|
apiErr := api.AsServerError(err)
|
|
require.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusBadRequest, apiErr.Response().StatusCode())
|
|
require.Len(apiErr.Details.RequestFields, 1)
|
|
assert.Equal(apiErr.Details.RequestFields[0].Name, "id")
|
|
|
|
// Updating using WithAliases should fail.
|
|
_, err = tarClient.Update(tc.Context(), tar.Item.Id, tar.Item.Version, targets.WithAliases([]targets.Alias{{Value: "alias1", ScopeId: "global"}}))
|
|
require.Error(err)
|
|
apiErr = api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusBadRequest, apiErr.Response().StatusCode())
|
|
|
|
// Updating the wrong version should fail.
|
|
_, err = tarClient.Update(tc.Context(), tar.Item.Id, 73, targets.WithName("anything"))
|
|
require.Error(err)
|
|
apiErr = api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
|
|
|
tar, err = tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("foo"))
|
|
require.Error(err)
|
|
apiErr = api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.Nil(tar)
|
|
|
|
_, err = tarClient.Read(tc.Context(), globals.TcpTargetPrefix+"_doesntexis")
|
|
require.Error(err)
|
|
apiErr = api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
|
|
|
_, err = tarClient.Read(tc.Context(), "invalid id")
|
|
require.Error(err)
|
|
apiErr = api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
|
|
|
// reading by alias with no destination id should fail
|
|
rw := db.New(tc.DbConn())
|
|
al := aliastar.TestAlias(t, rw, "alias.value")
|
|
_, err = tarClient.Read(tc.Context(), al.GetValue())
|
|
require.Error(err)
|
|
apiErr = api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
|
|
|
client.SetToken("at_1234567890_madeupinvalidtoken")
|
|
tarClient = targets.NewClient(client)
|
|
_, err = tarClient.Read(tc.Context(), validTargetId)
|
|
apiErr = api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusUnauthorized, apiErr.Response().StatusCode())
|
|
}
|
|
|
|
func TestCreateTarget_WhitespaceInAddress(t *testing.T) {
|
|
require := require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
|
|
tarClient := targets.NewClient(client)
|
|
|
|
tar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("foo"), targets.WithTcpTargetDefaultPort(2), targets.WithAddress(" 127.0.0.1 "))
|
|
require.NoError(err)
|
|
require.NotNil(tar)
|
|
require.Equal("127.0.0.1", tar.GetItem().Address)
|
|
}
|
|
|
|
func TestUpdateTarget_WhitespaceInAddress(t *testing.T) {
|
|
require := require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
|
|
tarClient := targets.NewClient(client)
|
|
|
|
tar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("foo"), targets.WithTcpTargetDefaultPort(2), targets.WithAddress("127.0.0.1"))
|
|
require.NoError(err)
|
|
require.NotNil(tar)
|
|
|
|
updateResult, err := tarClient.Update(tc.Context(), tar.Item.Id, tar.Item.Version, targets.WithAddress(" 10.0.0.1 "))
|
|
require.NoError(err)
|
|
require.NotNil(updateResult)
|
|
require.Equal("10.0.0.1", updateResult.Item.Address)
|
|
}
|
|
|
|
// TestCreateTarget_SlashesInName verifies that we can prop'ly route when using
|
|
// a target name for authorizing a session and the name contains slashes
|
|
func TestCreateTarget_SlashesInName(t *testing.T) {
|
|
require := require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
|
|
tw, _ := worker.NewAuthorizedPkiTestWorker(t, tc.ServersRepo(), "test", tc.ClusterAddrs())
|
|
require.NotNil(tw)
|
|
|
|
helper.ExpectWorkers(t, tc, tw)
|
|
// Wait for an extra routing info update for good measure
|
|
// TODO(https://hashicorp.atlassian.net/browse/ICU-16124): why is this necessary?
|
|
require.NoError(tw.Worker().WaitForNextSuccessfulRoutingInfoUpdate())
|
|
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
|
|
tarClient := targets.NewClient(client)
|
|
|
|
tar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("foo/bar"), targets.WithTcpTargetDefaultPort(2), targets.WithAddress("127.0.0.1"))
|
|
require.NoError(err)
|
|
require.NotNil(tar)
|
|
|
|
authzResult, err := tarClient.AuthorizeSession(tc.Context(), "", targets.WithName("foo/bar"), targets.WithScopeId(proj.PublicId))
|
|
require.NoError(err)
|
|
require.NotNil(authzResult)
|
|
}
|