From 732973c7b86d033d8ece0de2353c2e265d5be4d8 Mon Sep 17 00:00:00 2001 From: Stan Ryzhov <60649800+stasryzhov@users.noreply.github.com> Date: Thu, 6 Jul 2023 16:41:39 -0400 Subject: [PATCH] test(e2e): Add test to connect to target via its name and scope (#3387) --- testing/internal/e2e/boundary/scope.go | 50 ++++++++++-- testing/internal/e2e/boundary/target.go | 6 +- .../e2e/tests/base/target_tcp_connect_test.go | 77 +++++++++++++++++++ 3 files changed, 125 insertions(+), 8 deletions(-) diff --git a/testing/internal/e2e/boundary/scope.go b/testing/internal/e2e/boundary/scope.go index bb81d0da3c..777cf6a295 100644 --- a/testing/internal/e2e/boundary/scope.go +++ b/testing/internal/e2e/boundary/scope.go @@ -64,14 +64,24 @@ func CreateNewOrgCli(t testing.TB, ctx context.Context) string { // CreateNewProjectCli creates a new project in boundary using the cli. The project will be created // under the provided org id. // Returns the id of the new project. -func CreateNewProjectCli(t testing.TB, ctx context.Context, orgId string) string { +func CreateNewProjectCli(t testing.TB, ctx context.Context, orgId string, opt ...ScopeOption) string { + opts := getScopeOpts(opt...) + var args []string + + args = append(args, + "scopes", "create", + "-scope-id", orgId, + "-format", "json", + ) + + if opts.WithName != "" { + args = append(args, "-name", opts.WithName) + } else { + args = append(args, "-name", "e2e Project") + } + output := e2e.RunCommand(ctx, "boundary", - e2e.WithArgs( - "scopes", "create", - "-name", "e2e Project", - "-scope-id", orgId, - "-format", "json", - ), + e2e.WithArgs(args...), ) require.NoError(t, output.Err, string(output.Stderr)) @@ -83,3 +93,29 @@ func CreateNewProjectCli(t testing.TB, ctx context.Context, orgId string) string t.Logf("Created Project Id: %s", newProjectId) return newProjectId } + +// getScopeOpts iterates the inbound ScopeOptions and returns a struct +func getScopeOpts(opt ...ScopeOption) scopeOptions { + opts := scopeOptions{ + WithName: "", + } + for _, o := range opt { + o(&opts) + } + return opts +} + +// ScopeOption represents how Options are passed as arguments +type ScopeOption func(*scopeOptions) + +// scopeOptions is a struct representing available options for scopes +type scopeOptions struct { + WithName string +} + +// WithName provides an option to search by a friendly name +func WithName(name string) ScopeOption { + return func(o *scopeOptions) { + o.WithName = name + } +} diff --git a/testing/internal/e2e/boundary/target.go b/testing/internal/e2e/boundary/target.go index 4d0f06d1ed..171f792526 100644 --- a/testing/internal/e2e/boundary/target.go +++ b/testing/internal/e2e/boundary/target.go @@ -60,10 +60,14 @@ func CreateNewTargetCli(t testing.TB, ctx context.Context, projectId string, def args = append(args, "-scope-id", projectId, "-default-port", defaultPort, - "-name", "e2e Target", "-format", "json", ) + if opts.WithName != "" { + args = append(args, "-name", opts.WithName) + } else { + args = append(args, "-name", "e2e Target") + } if opts.WithAddress != "" { args = append(args, "-address", opts.WithAddress) } diff --git a/testing/internal/e2e/tests/base/target_tcp_connect_test.go b/testing/internal/e2e/tests/base/target_tcp_connect_test.go index 896cc1c670..95ec27859b 100644 --- a/testing/internal/e2e/tests/base/target_tcp_connect_test.go +++ b/testing/internal/e2e/tests/base/target_tcp_connect_test.go @@ -65,6 +65,83 @@ func TestCliTcpTargetConnectTargetBasic(t *testing.T) { t.Log("Successfully connected to target") } +// TestCliTcpTargetConnectTargetBasic uses the boundary cli to create a number of +// supporting objects to connect to a target. It then attempts to connect to +// that target via the combination of target name and target scope name, +// and verifies that the connection was successful. +func TestCliTcpTargetConnectTargetViaTargetAndScopeNames(t *testing.T) { + e2e.MaybeSkipTest(t) + c, err := loadTestConfig() + require.NoError(t, err) + + ctx := context.Background() + boundary.AuthenticateAdminCli(t, ctx) + newOrgId := boundary.CreateNewOrgCli(t, ctx) + t.Cleanup(func() { + ctx := context.Background() + boundary.AuthenticateAdminCli(t, ctx) + output := e2e.RunCommand(ctx, "boundary", e2e.WithArgs("scopes", "delete", "-id", newOrgId)) + require.NoError(t, output.Err, string(output.Stderr)) + }) + testProjectName := `E2E/Project-With\Name` + testTargetName := `E2E/Test-Target-With\Name` + newProjectId := boundary.CreateNewProjectCli(t, ctx, newOrgId, boundary.WithName(testProjectName)) + newHostCatalogId := boundary.CreateNewHostCatalogCli(t, ctx, newProjectId) + newHostSetId := boundary.CreateNewHostSetCli(t, ctx, newHostCatalogId) + newHostId := boundary.CreateNewHostCli(t, ctx, newHostCatalogId, c.TargetIp) + boundary.AddHostToHostSetCli(t, ctx, newHostSetId, newHostId) + newTargetId := boundary.CreateNewTargetCli(t, ctx, newProjectId, c.TargetPort, target.WithName(testTargetName)) + boundary.AddHostSourceToTargetCli(t, ctx, newTargetId, newHostSetId) + + // Connect to target via target and scope names, and print host's IP address + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "connect", + "-target-name", testTargetName, + "-target-scope-name", testProjectName, + "-exec", "/usr/bin/ssh", "--", + "-l", c.TargetSshUser, + "-i", c.TargetSshKeyPath, + "-o", "UserKnownHostsFile=/dev/null", + "-o", "StrictHostKeyChecking=no", + "-o", "IdentitiesOnly=yes", // forces the use of the provided key + "-p", "{{boundary.port}}", // this is provided by boundary + "{{boundary.ip}}", + "hostname", "-i", + ), + ) + require.NoError(t, output.Err, string(output.Stderr)) + + parts := strings.Fields(string(output.Stdout)) + hostIp := parts[len(parts)-1] + require.Equal(t, c.TargetIp, hostIp, "SSH session did not return expected output") + t.Log("Successfully connected to target by its name and scope name") + + // Connect to target via target name and scope ID, and print host's IP address + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "connect", + "-target-name", testTargetName, + "-target-scope-id", newProjectId, + "-exec", "/usr/bin/ssh", "--", + "-l", c.TargetSshUser, + "-i", c.TargetSshKeyPath, + "-o", "UserKnownHostsFile=/dev/null", + "-o", "StrictHostKeyChecking=no", + "-o", "IdentitiesOnly=yes", // forces the use of the provided key + "-p", "{{boundary.port}}", // this is provided by boundary + "{{boundary.ip}}", + "hostname", "-i", + ), + ) + require.NoError(t, output.Err, string(output.Stderr)) + + parts = strings.Fields(string(output.Stdout)) + hostIp = parts[len(parts)-1] + require.Equal(t, c.TargetIp, hostIp, "SSH session did not return expected output") + t.Log("Successfully connected to target by its name and scope ID") +} + func TestCliTcpTargetConnectTargetWithTargetClientPort(t *testing.T) { e2e.MaybeSkipTest(t) c, err := loadTestConfig()