diff --git a/testing/internal/e2e/host/static/connect_authz_token_test.go b/testing/internal/e2e/host/static/connect_authz_token_test.go new file mode 100644 index 0000000000..b4ac2cadd1 --- /dev/null +++ b/testing/internal/e2e/host/static/connect_authz_token_test.go @@ -0,0 +1,117 @@ +package static_test + +import ( + "encoding/json" + "fmt" + "os" + "strings" + "testing" + + "github.com/hashicorp/boundary/api/credentials" + "github.com/hashicorp/boundary/api/credentialstores" + "github.com/hashicorp/boundary/api/targets" + "github.com/hashicorp/boundary/testing/internal/e2e" + "github.com/hashicorp/boundary/testing/internal/e2e/boundary" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestConnectTargetWithAuthzTokenCli uses the boundary cli to connect to a target using the +// `authz_token` option +func TestConnectTargetWithAuthzTokenCli(t *testing.T) { + e2e.MaybeSkipTest(t) + c, err := loadConfig() + require.NoError(t, err) + + boundary.AuthenticateCli(t) + newOrgId := boundary.CreateNewOrgCli(t) + newProjectId := boundary.CreateNewProjectCli(t, newOrgId) + newHostCatalogId := boundary.CreateNewHostCatalogCli(t, newProjectId) + newHostSetId := boundary.CreateNewHostSetCli(t, newHostCatalogId) + newHostId := boundary.CreateNewHostCli(t, newHostCatalogId, c.TargetIp) + boundary.AddHostToHostSetCli(t, newHostSetId, newHostId) + newTargetId := boundary.CreateNewTargetCli(t, newProjectId, c.TargetPort) + boundary.AddHostSourceToTargetCli(t, newTargetId, newHostSetId) + + // Create a credential store + output := e2e.RunCommand("boundary", "credential-stores", "create", "static", + "-scope-id", newProjectId, + "-format", "json", + ) + require.NoError(t, output.Err, string(output.Stderr)) + var newCredentialStoreResult credentialstores.CredentialStoreCreateResult + err = json.Unmarshal(output.Stdout, &newCredentialStoreResult) + require.NoError(t, err) + newCredentialStoreId := newCredentialStoreResult.Item.Id + t.Logf("Created Credential Store: %s", newCredentialStoreId) + + // Create credentials + output = e2e.RunCommand("boundary", "credentials", "create", "ssh-private-key", + "-credential-store-id", newCredentialStoreId, + "-username", c.TargetSshUser, + "-private-key", "file://"+c.TargetSshKeyPath, + "-format", "json", + ) + require.NoError(t, output.Err, string(output.Stderr)) + var newCredentialsResult credentials.CredentialCreateResult + err = json.Unmarshal(output.Stdout, &newCredentialsResult) + require.NoError(t, err) + newCredentialsId := newCredentialsResult.Item.Id + t.Logf("Created Credentials: %s", newCredentialsId) + + // Add credentials to target + output = e2e.RunCommand("boundary", "targets", "add-credential-sources", + "-id", newTargetId, + "-brokered-credential-source", newCredentialsId, + ) + require.NoError(t, output.Err, string(output.Stderr)) + + // Get credentials for target + output = e2e.RunCommand("boundary", "targets", "authorize-session", "-id", newTargetId, "-format", "json") + require.NoError(t, output.Err, string(output.Stderr)) + var newSessionAuthorizationResult targets.SessionAuthorizationResult + err = json.Unmarshal(output.Stdout, &newSessionAuthorizationResult) + require.NoError(t, err) + + newSessionAuthorization := newSessionAuthorizationResult.Item + retrievedUser := fmt.Sprintf("%s", newSessionAuthorization.Credentials[0].Credential["username"]) + retrievedKey := fmt.Sprintf("%s\n", newSessionAuthorization.Credentials[0].Credential["private_key"]) + assert.Equal(t, c.TargetSshUser, retrievedUser) + + k, err := os.ReadFile(c.TargetSshKeyPath) + require.NoError(t, err) + require.Equal(t, string(k), retrievedKey) + t.Log("Successfully retrieved credentials for target") + + // Get auth token for session + newAuthToken := newSessionAuthorizationResult.Item.AuthorizationToken + + // Create key file + retrievedKeyPath := fmt.Sprintf("%s/%s", t.TempDir(), "target_private_key.pem") + f, err := os.Create(retrievedKeyPath) + require.NoError(t, err) + _, err = f.WriteString(retrievedKey) + require.NoError(t, err) + err = os.Chmod(retrievedKeyPath, 0o400) + require.NoError(t, err) + + // Connect to target and print host's IP address using retrieved credentials + output = e2e.RunCommand("boundary", "connect", + "-authz-token", newAuthToken, + "-exec", "/usr/bin/ssh", "--", + "-l", retrievedUser, + "-i", retrievedKeyPath, + "-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") +} diff --git a/testing/internal/e2e/host/static/connect_ssh_test.go b/testing/internal/e2e/host/static/connect_ssh_test.go index afa143d31e..58d3b1a291 100644 --- a/testing/internal/e2e/host/static/connect_ssh_test.go +++ b/testing/internal/e2e/host/static/connect_ssh_test.go @@ -16,10 +16,10 @@ import ( "github.com/stretchr/testify/require" ) -// TestConnectTargetWithStaticCredentialStoreCli uses the boundary cli to create a credential using -// boundary's built-in credential store. The test attaches that credential to a target and attempts -// to connect to that target using those credentials. -func TestConnectTargetWithStaticCredentialStoreCli(t *testing.T) { +// TestConnectTargetWithSshCli uses the boundary cli to create a credential using boundary's +// built-in credential store. The test attaches that credential to a target and attempts to connect +// to that target using those credentials. +func TestConnectTargetWithSshCli(t *testing.T) { e2e.MaybeSkipTest(t) c, err := loadConfig() require.NoError(t, err) @@ -141,4 +141,14 @@ func TestCreateTargetWithStaticCredentialStoreApi(t *testing.T) { targets.WithBrokeredCredentialSourceIds([]string{newCredentialsId}), ) require.NoError(t, err) + + // Authorize Session + newSessionAuthorizationResult, err := tClient.AuthorizeSession(ctx, newTargetId) + require.NoError(t, err) + newSessionAuthorization := newSessionAuthorizationResult.Item + retrievedUser := fmt.Sprintf("%s", newSessionAuthorization.Credentials[0].Credential["username"]) + retrievedKey := fmt.Sprintf("%s", newSessionAuthorization.Credentials[0].Credential["private_key"]) + assert.Equal(t, c.TargetSshUser, retrievedUser) + require.Equal(t, string(k), retrievedKey) + t.Log("Successfully retrieved credentials for target") }