// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package static_test import ( "context" "encoding/json" "fmt" "strings" "testing" "time" "github.com/hashicorp/boundary/testing/internal/e2e" "github.com/hashicorp/boundary/testing/internal/e2e/boundary" "github.com/stretchr/testify/require" ) func TestCliConnectTargetWithLocalhost(t *testing.T) { e2e.MaybeSkipTest(t) c, err := loadConfig() 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) 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) boundary.AddHostSourceToTargetCli(t, ctx, newTargetId, newHostSetId) // 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 target and print host's IP address output := e2e.RunCommand(ctx, "ssh", e2e.WithArgs( "localhost", "-p", port, "-l", c.TargetSshUser, "-i", c.TargetSshKeyPath, "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no", "-o", "IdentitiesOnly=yes", // forces the use of the provided key "hostname -i", ), ) require.NoError(t, output.Err, string(output.Stderr)) require.Equal(t, c.TargetIp, strings.TrimSpace(string(output.Stdout))) // Cancel session cancel() // Check output from session select { case output := <-cmdChan: type connectOutput struct { Port int } var response connectOutput err = json.Unmarshal(output.Stdout, &response) require.NoError(t, err) require.Equal(t, port, fmt.Sprint(response.Port)) case <-time.After(time.Second * 5): t.Fatal("Timed out waiting for session command to exit") } }