* test(e2e): Add more "session end" tests These tests validate that the session ends when the respective project or target is deleted. It also ensures that the session can still be read after the deletion of the corresponding item. * Removing test from PR due to bug This test found a bug that will be resolved in the future. Taking this test out of the PR and will add it once the bug is fixed.
209 lines
7.5 KiB
Go
209 lines
7.5 KiB
Go
package static_test
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hashicorp/boundary/api/accounts"
|
|
"github.com/hashicorp/boundary/api/roles"
|
|
"github.com/hashicorp/boundary/api/scopes"
|
|
"github.com/hashicorp/boundary/api/sessions"
|
|
"github.com/hashicorp/boundary/api/users"
|
|
"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"
|
|
)
|
|
|
|
// TestCliSessionCancelUser uses the cli to create a new user and sets up the right permissions for
|
|
// the user to connect to the created target. The test also confirms that an admin can cancel the
|
|
// user's session.
|
|
func TestCliSessionCancelUser(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)
|
|
acctName := "e2e-account"
|
|
newAccountId, acctPassword := boundary.CreateNewAccountCli(t, ctx, acctName)
|
|
t.Cleanup(func() {
|
|
boundary.AuthenticateAdminCli(t, context.Background())
|
|
output := e2e.RunCommand(ctx, "boundary",
|
|
e2e.WithArgs("accounts", "delete", "-id", newAccountId),
|
|
)
|
|
require.NoError(t, output.Err, string(output.Stderr))
|
|
})
|
|
newUserId := boundary.CreateNewUserCli(t, ctx, "global")
|
|
t.Cleanup(func() {
|
|
boundary.AuthenticateAdminCli(t, context.Background())
|
|
output := e2e.RunCommand(ctx, "boundary",
|
|
e2e.WithArgs("users", "delete", "-id", newUserId),
|
|
)
|
|
require.NoError(t, output.Err, string(output.Stderr))
|
|
})
|
|
boundary.SetAccountToUserCli(t, ctx, newUserId, newAccountId)
|
|
|
|
// Try to connect to the target as a user without permissions
|
|
boundary.AuthenticateCli(t, ctx, acctName, acctPassword)
|
|
output := e2e.RunCommand(ctx, "boundary",
|
|
e2e.WithArgs(
|
|
"connect",
|
|
"-target-id", newTargetId,
|
|
"-format", "json",
|
|
"-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.Error(t, output.Err, string(output.Stdout), string(output.Stderr))
|
|
var response boundary.CliError
|
|
err = json.Unmarshal(output.Stderr, &response)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 403, int(response.Status))
|
|
t.Log("Successfully received an error when connecting to target as a user without permissions")
|
|
|
|
// Create a role for user
|
|
boundary.AuthenticateAdminCli(t, ctx)
|
|
newRoleId := boundary.CreateNewRoleCli(t, ctx, newProjectId)
|
|
boundary.AddGrantToRoleCli(t, ctx, newRoleId, "id=*;type=target;actions=authorize-session")
|
|
boundary.AddPrincipalToRoleCli(t, ctx, newRoleId, newUserId)
|
|
|
|
// Connect to target to create a session
|
|
ctxCancel, cancel := context.WithCancel(context.Background())
|
|
errChan := make(chan *e2e.CommandResult)
|
|
go func() {
|
|
token := boundary.GetAuthenticationTokenCli(t, ctx, acctName, acctPassword)
|
|
t.Log("Starting session as user...")
|
|
errChan <- e2e.RunCommand(ctxCancel, "boundary",
|
|
e2e.WithArgs(
|
|
"connect",
|
|
"-token", "env://E2E_AUTH_TOKEN",
|
|
"-target-id", newTargetId,
|
|
"-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; sleep 60",
|
|
),
|
|
e2e.WithEnv("E2E_AUTH_TOKEN", token),
|
|
)
|
|
}()
|
|
t.Cleanup(cancel)
|
|
session := boundary.WaitForSessionToBeActiveCli(t, ctx, newProjectId)
|
|
assert.Equal(t, newTargetId, session.TargetId)
|
|
assert.Equal(t, newHostId, session.HostId)
|
|
|
|
// Cancel session
|
|
t.Log("Canceling session...")
|
|
output = e2e.RunCommand(ctx, "boundary",
|
|
e2e.WithArgs("sessions", "cancel", "-id", session.Id),
|
|
)
|
|
require.NoError(t, output.Err, string(output.Stderr))
|
|
|
|
output = e2e.RunCommand(ctx, "boundary",
|
|
e2e.WithArgs("sessions", "read", "-id", session.Id, "-format", "json"),
|
|
)
|
|
require.NoError(t, output.Err, string(output.Stderr))
|
|
var newSessionReadResult sessions.SessionReadResult
|
|
err = json.Unmarshal(output.Stdout, &newSessionReadResult)
|
|
require.NoError(t, err)
|
|
require.Condition(t, func() bool {
|
|
return newSessionReadResult.Item.Status == "canceling" || newSessionReadResult.Item.Status == "terminated"
|
|
})
|
|
|
|
// Check output from session
|
|
select {
|
|
case output := <-errChan:
|
|
// `boundary connect` returns a 255 when cancelled
|
|
require.Equal(t, output.ExitCode, 255, string(output.Stdout), string(output.Stderr))
|
|
case <-time.After(time.Second * 5):
|
|
t.Fatal("Timed out waiting for session command to exit")
|
|
}
|
|
|
|
t.Log("Successfully cancelled session")
|
|
}
|
|
|
|
// TestApiCreateUser uses the Go api to create a new user and add some grants to the user
|
|
func TestApiCreateUser(t *testing.T) {
|
|
e2e.MaybeSkipTest(t)
|
|
c, err := loadConfig()
|
|
require.NoError(t, err)
|
|
|
|
client, err := boundary.NewApiClient()
|
|
require.NoError(t, err)
|
|
ctx := context.Background()
|
|
|
|
newOrgId := boundary.CreateNewOrgApi(t, ctx, client)
|
|
t.Cleanup(func() {
|
|
scopeClient := scopes.NewClient(client)
|
|
_, err := scopeClient.Delete(ctx, newOrgId)
|
|
require.NoError(t, err)
|
|
})
|
|
newProjectId := boundary.CreateNewProjectApi(t, ctx, client, newOrgId)
|
|
newHostCatalogId := boundary.CreateNewHostCatalogApi(t, ctx, client, newProjectId)
|
|
newHostSetId := boundary.CreateNewHostSetApi(t, ctx, client, newHostCatalogId)
|
|
newHostId := boundary.CreateNewHostApi(t, ctx, client, newHostCatalogId, c.TargetIp)
|
|
boundary.AddHostToHostSetApi(t, ctx, client, newHostSetId, newHostId)
|
|
newTargetId := boundary.CreateNewTargetApi(t, ctx, client, newProjectId, c.TargetPort)
|
|
boundary.AddHostSourceToTargetApi(t, ctx, client, newTargetId, newHostSetId)
|
|
|
|
acctName := "e2e-account"
|
|
newAcctId, _ := boundary.CreateNewAccountApi(t, ctx, client, acctName)
|
|
t.Cleanup(func() {
|
|
aClient := accounts.NewClient(client)
|
|
_, err := aClient.Delete(ctx, newAcctId)
|
|
require.NoError(t, err)
|
|
})
|
|
newUserId := boundary.CreateNewUserApi(t, ctx, client, "global")
|
|
t.Cleanup(func() {
|
|
uClient := users.NewClient(client)
|
|
_, err := uClient.Delete(ctx, newUserId)
|
|
require.NoError(t, err)
|
|
})
|
|
uClient := users.NewClient(client)
|
|
uClient.SetAccounts(ctx, newUserId, 0, []string{newAcctId})
|
|
|
|
rClient := roles.NewClient(client)
|
|
newRoleResult, err := rClient.Create(ctx, newProjectId)
|
|
require.NoError(t, err)
|
|
newRoleId := newRoleResult.Item.Id
|
|
t.Logf("Created Role: %s", newRoleId)
|
|
|
|
_, err = rClient.AddGrants(ctx, newRoleId, 0, []string{"id=*;type=target;actions=authorize-session"},
|
|
roles.WithAutomaticVersioning(true),
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
_, err = rClient.AddPrincipals(ctx, newRoleId, 0, []string{newUserId},
|
|
roles.WithAutomaticVersioning(true),
|
|
)
|
|
require.NoError(t, err)
|
|
}
|