From 36d0e5ede03ae21f9497a6840b98c82fb9e601fb Mon Sep 17 00:00:00 2001 From: Michael Li Date: Tue, 14 Nov 2023 14:54:48 -0500 Subject: [PATCH] test(e2e): Add test that connects to target using go ssh library (#4040) * test(e2e): Add test that connects to target using golang ssh library * fixup! test(e2e): Add test that connects to target using golang ssh library --- .../base/target_tcp_connect_go_ssh_test.go | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 testing/internal/e2e/tests/base/target_tcp_connect_go_ssh_test.go diff --git a/testing/internal/e2e/tests/base/target_tcp_connect_go_ssh_test.go b/testing/internal/e2e/tests/base/target_tcp_connect_go_ssh_test.go new file mode 100644 index 000000000..20b551242 --- /dev/null +++ b/testing/internal/e2e/tests/base/target_tcp_connect_go_ssh_test.go @@ -0,0 +1,86 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package base_test + +import ( + "context" + "fmt" + "os" + "strings" + "testing" + + "github.com/hashicorp/boundary/internal/target" + "github.com/hashicorp/boundary/testing/internal/e2e" + "github.com/hashicorp/boundary/testing/internal/e2e/boundary" + "github.com/stretchr/testify/require" + "golang.org/x/crypto/ssh" +) + +// TestCliTcpTargetConnectGoSsh uses the go experimental ssh library to connect to a target +func TestCliTcpTargetConnectGoSsh(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)) + }) + newProjectId := boundary.CreateNewProjectCli(t, ctx, newOrgId) + newTargetId := boundary.CreateNewTargetCli(t, ctx, newProjectId, c.TargetPort, target.WithAddress(c.TargetAddress)) + + // Start a session + ctxCancel, cancel := context.WithCancel(context.Background()) + port := "12345" + cmdChan := make(chan *e2e.CommandResult) + go func() { + t.Log("Starting session...") + cmdChan <- e2e.RunCommand(ctxCancel, "boundary", + e2e.WithArgs( + "connect", + "-target-id", newTargetId, + "-listen-port", port, + "-format", "json", + ), + ) + }() + t.Cleanup(cancel) + + boundary.WaitForSessionCli(t, ctx, newProjectId) + + // Connect to the target using the go experimental ssh library + privateKeyRaw, err := os.ReadFile(c.TargetSshKeyPath) + require.NoError(t, err) + signer, err := ssh.ParsePrivateKey(privateKeyRaw) + require.NoError(t, err) + + config := &ssh.ClientConfig{ + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + User: c.TargetSshUser, + Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)}, + } + client, err := ssh.Dial("tcp", fmt.Sprintf("localhost:%s", port), config) + require.NoError(t, err) + t.Cleanup(func() { client.Close() }) + + // Run a command and validate its output + session, err := client.NewSession() + require.NoError(t, err) + t.Cleanup(func() { session.Close() }) + output, err := session.CombinedOutput("hostname -i") + require.NoError(t, err, string(output)) + require.Equal(t, c.TargetAddress, strings.TrimSpace(string(output))) + + // Run a command and expect an error + sessionWithError, err := client.NewSession() + require.NoError(t, err) + t.Cleanup(func() { sessionWithError.Close() }) + output, err = sessionWithError.CombinedOutput("rm test.txt") + require.Error(t, err, string(output)) +}