diff --git a/testing/internal/e2e/boundary/account.go b/testing/internal/e2e/boundary/account.go new file mode 100644 index 000000000..aa297aea3 --- /dev/null +++ b/testing/internal/e2e/boundary/account.go @@ -0,0 +1,78 @@ +package boundary + +import ( + "context" + "encoding/json" + "testing" + + "github.com/hashicorp/boundary/api" + "github.com/hashicorp/boundary/api/accounts" + "github.com/hashicorp/boundary/testing/internal/e2e" + "github.com/hashicorp/go-secure-stdlib/base62" + "github.com/stretchr/testify/require" +) + +// CreateNewAccountApi creates a new account using the Go api. +// Returns the id of the new account as well as the password that was generated +func CreateNewAccountApi(t testing.TB, ctx context.Context, client *api.Client, loginName string) (accountId string, password string) { + c, err := loadConfig() + require.NoError(t, err) + + aClient := accounts.NewClient(client) + password, err = base62.Random(16) + require.NoError(t, err) + newAccountResult, err := aClient.Create(ctx, c.AuthMethodId, + accounts.WithPasswordAccountLoginName(loginName), + accounts.WithPasswordAccountPassword(password), + ) + require.NoError(t, err) + + accountId = newAccountResult.Item.Id + t.Logf("Create Account: %s", accountId) + t.Cleanup(func() { + _, err := aClient.Delete(ctx, accountId) + require.NoError(t, err) + }) + + return +} + +// CreateNewAccountCli creates a new account using the cli. +// Returns the id of the new account as well as the password that was generated +func CreateNewAccountCli(t testing.TB, ctx context.Context, loginName string) (string, string) { + c, err := loadConfig() + require.NoError(t, err) + + password, err := base62.Random(16) + require.NoError(t, err) + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "accounts", "create", "password", + "-auth-method-id", c.AuthMethodId, + "-login-name", loginName, + "-password", "env://E2E_TEST_ACCOUNT_PASSWORD", + "-name", "e2e Account "+loginName, + "-description", "e2e Account", + "-format", "json", + ), + e2e.WithEnv("E2E_TEST_ACCOUNT_PASSWORD", password), + ) + require.NoError(t, output.Err, string(output.Stderr)) + + var newAccountResult accounts.AccountCreateResult + err = json.Unmarshal(output.Stdout, &newAccountResult) + require.NoError(t, err) + + newAccountId := newAccountResult.Item.Id + t.Cleanup(func() { + AuthenticateAdminCli(t, context.Background()) + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs("accounts", "delete", "-id", newAccountId), + ) + require.NoError(t, output.Err, string(output.Stderr)) + }) + + t.Logf("Created Account: %s", newAccountId) + + return newAccountId, password +} diff --git a/testing/internal/e2e/boundary/boundary.go b/testing/internal/e2e/boundary/boundary.go index 313e4a57d..e972362b6 100644 --- a/testing/internal/e2e/boundary/boundary.go +++ b/testing/internal/e2e/boundary/boundary.go @@ -59,16 +59,28 @@ func NewApiClient() (*api.Client, error) { return client, err } -// AuthenticateCli uses the cli to authenticate the specified Boundary instance. -func AuthenticateCli(t testing.TB) { +// AuthenticateAdminCli uses the cli to authenticate the specified Boundary instance as an admin +func AuthenticateAdminCli(t testing.TB, ctx context.Context) { c, err := loadConfig() require.NoError(t, err) - output := e2e.RunCommand(context.Background(), "boundary", "authenticate", "password", - "-addr", c.Address, - "-auth-method-id", c.AuthMethodId, - "-login-name", c.AdminLoginName, - "-password", "env://E2E_PASSWORD_ADMIN_PASSWORD", + AuthenticateCli(t, ctx, c.AdminLoginName, c.AdminLoginPassword) +} + +// AuthenticateCli uses the cli to authenticate the specified Boundary instance +func AuthenticateCli(t testing.TB, ctx context.Context, loginName string, password string) { + c, err := loadConfig() + require.NoError(t, err) + + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "authenticate", "password", + "-addr", c.Address, + "-auth-method-id", c.AuthMethodId, + "-login-name", loginName, + "-password", "env://E2E_TEST_BOUNDARY_PASSWORD", + ), + e2e.WithEnv("E2E_TEST_BOUNDARY_PASSWORD", password), ) require.NoError(t, output.Err, string(output.Stderr)) } diff --git a/testing/internal/e2e/boundary/credential.go b/testing/internal/e2e/boundary/credential.go index c9b9b64be..51189afe1 100644 --- a/testing/internal/e2e/boundary/credential.go +++ b/testing/internal/e2e/boundary/credential.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/require" ) -// CreateNewCredentialStoreStaticApi creates a new static credential store using the go api. +// CreateNewCredentialStoreStaticApi creates a new static credential store using the Go api. // Returns the id of the new credential store func CreateNewCredentialStoreStaticApi(t testing.TB, ctx context.Context, client *api.Client, projectId string) string { csClient := credentialstores.NewClient(client) @@ -25,10 +25,13 @@ func CreateNewCredentialStoreStaticApi(t testing.TB, ctx context.Context, client // CreateNewCredentialStoreStaticCli creates a new static credential store using the cli. // Returns the id of the new credential store -func CreateNewCredentialStoreStaticCli(t testing.TB, projectId string) string { - output := e2e.RunCommand(context.Background(), "boundary", "credential-stores", "create", "static", - "-scope-id", projectId, - "-format", "json", +func CreateNewCredentialStoreStaticCli(t testing.TB, ctx context.Context, projectId string) string { + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "credential-stores", "create", "static", + "-scope-id", projectId, + "-format", "json", + ), ) require.NoError(t, output.Err, string(output.Stderr)) var newCredentialStoreResult credentialstores.CredentialStoreCreateResult diff --git a/testing/internal/e2e/boundary/host.go b/testing/internal/e2e/boundary/host.go index 786561bff..9f01e3d07 100644 --- a/testing/internal/e2e/boundary/host.go +++ b/testing/internal/e2e/boundary/host.go @@ -13,7 +13,7 @@ import ( "github.com/stretchr/testify/require" ) -// CreateNewHostCatalogApi creates a new host catalog in boundary using the go api. +// CreateNewHostCatalogApi creates a new host catalog in boundary using the Go api. // Returns the id of the new host catalog. func CreateNewHostCatalogApi(t testing.TB, ctx context.Context, client *api.Client, projectId string) string { hcClient := hostcatalogs.NewClient(client) @@ -25,7 +25,7 @@ func CreateNewHostCatalogApi(t testing.TB, ctx context.Context, client *api.Clie return newHostCatalogId } -// CreateNewHostSetApi creates a new host set in boundary using the go api. +// CreateNewHostSetApi creates a new host set in boundary using the Go api. // Returns the id of the new host set. func CreateNewHostSetApi(t testing.TB, ctx context.Context, client *api.Client, hostCatalogId string) string { hsClient := hostsets.NewClient(client) @@ -37,7 +37,7 @@ func CreateNewHostSetApi(t testing.TB, ctx context.Context, client *api.Client, return newHostSetId } -// CreateNewHostApi creates a new host in boundary using the go api +// CreateNewHostApi creates a new host in boundary using the Go api // Returns the id of the new host. func CreateNewHostApi(t testing.TB, ctx context.Context, client *api.Client, hostCatalogId string, address string) string { hClient := hosts.NewClient(client) @@ -52,7 +52,7 @@ func CreateNewHostApi(t testing.TB, ctx context.Context, client *api.Client, hos return newHostId } -// AddHostToHostSetApi adds a host to a host set using the go api +// AddHostToHostSetApi adds a host to a host set using the Go api func AddHostToHostSetApi(t testing.TB, ctx context.Context, client *api.Client, hostSetId string, hostId string) { hsClient := hostsets.NewClient(client) _, err := hsClient.AddHosts(ctx, hostSetId, 0, []string{hostId}, hostsets.WithAutomaticVersioning(true)) @@ -61,11 +61,14 @@ func AddHostToHostSetApi(t testing.TB, ctx context.Context, client *api.Client, // CreateNewHostCatalogCli creates a new host catalog in boundary using the cli. // Returns the id of the new host catalog. -func CreateNewHostCatalogCli(t testing.TB, projectId string) string { - output := e2e.RunCommand(context.Background(), "boundary", "host-catalogs", "create", "static", - "-scope-id", projectId, - "-name", "e2e Host Catalog", - "-format", "json", +func CreateNewHostCatalogCli(t testing.TB, ctx context.Context, projectId string) string { + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "host-catalogs", "create", "static", + "-scope-id", projectId, + "-name", "e2e Host Catalog", + "-format", "json", + ), ) require.NoError(t, output.Err, string(output.Stderr)) var newHostCatalogResult hostcatalogs.HostCatalogCreateResult @@ -79,11 +82,14 @@ func CreateNewHostCatalogCli(t testing.TB, projectId string) string { // CreateNewHostSetCli creates a new host set in boundary using the cli. // Returns the id of the new host set. -func CreateNewHostSetCli(t testing.TB, hostCatalogId string) string { - output := e2e.RunCommand(context.Background(), "boundary", "host-sets", "create", "static", - "-host-catalog-id", hostCatalogId, - "-name", "e2e Host Set", - "-format", "json", +func CreateNewHostSetCli(t testing.TB, ctx context.Context, hostCatalogId string) string { + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "host-sets", "create", "static", + "-host-catalog-id", hostCatalogId, + "-name", "e2e Host Set", + "-format", "json", + ), ) require.NoError(t, output.Err, string(output.Stderr)) var newHostSetResult hostsets.HostSetCreateResult @@ -97,12 +103,15 @@ func CreateNewHostSetCli(t testing.TB, hostCatalogId string) string { // CreateNewHostCli creates a new host in boundary using the cli. // Returns the id of the new host. -func CreateNewHostCli(t testing.TB, hostCatalogId string, address string) string { - output := e2e.RunCommand(context.Background(), "boundary", "hosts", "create", "static", - "-host-catalog-id", hostCatalogId, - "-name", address, - "-address", address, - "-format", "json", +func CreateNewHostCli(t testing.TB, ctx context.Context, hostCatalogId string, address string) string { + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "hosts", "create", "static", + "-host-catalog-id", hostCatalogId, + "-name", address, + "-address", address, + "-format", "json", + ), ) require.NoError(t, output.Err, string(output.Stderr)) var newHostResult hosts.HostCreateResult @@ -115,7 +124,9 @@ func CreateNewHostCli(t testing.TB, hostCatalogId string, address string) string } // AddHostToHostSetCli adds a host to a host set using the cli -func AddHostToHostSetCli(t testing.TB, hostSetId string, hostId string) { - output := e2e.RunCommand(context.Background(), "boundary", "host-sets", "add-hosts", "-id", hostSetId, "-host", hostId) +func AddHostToHostSetCli(t testing.TB, ctx context.Context, hostSetId string, hostId string) { + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs("host-sets", "add-hosts", "-id", hostSetId, "-host", hostId), + ) require.NoError(t, output.Err, string(output.Stderr)) } diff --git a/testing/internal/e2e/boundary/scope.go b/testing/internal/e2e/boundary/scope.go index ec2188409..5e48300ad 100644 --- a/testing/internal/e2e/boundary/scope.go +++ b/testing/internal/e2e/boundary/scope.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/require" ) -// CreateNewOrgApi creates a new organization in boundary using the go api. +// CreateNewOrgApi creates a new organization in boundary using the Go api. // Returns the id of the new org. func CreateNewOrgApi(t testing.TB, ctx context.Context, client *api.Client) string { scopeClient := scopes.NewClient(client) @@ -28,7 +28,7 @@ func CreateNewOrgApi(t testing.TB, ctx context.Context, client *api.Client) stri return newOrgId } -// CreateNewProjectApi creates a new project in boundary using the go api. The project will be created +// CreateNewProjectApi creates a new project in boundary using the Go api. The project will be created // under the provided org id. // Returns the id of the new project. func CreateNewProjectApi(t testing.TB, ctx context.Context, client *api.Client, orgId string) string { @@ -43,12 +43,14 @@ func CreateNewProjectApi(t testing.TB, ctx context.Context, client *api.Client, // CreateNewOrgCli creates a new organization in boundary using the cli. // Returns the id of the new org. -func CreateNewOrgCli(t testing.TB) string { - ctx := context.Background() - output := e2e.RunCommand(ctx, "boundary", "scopes", "create", - "-name", "e2e Org", - "-scope-id", "global", - "-format", "json", +func CreateNewOrgCli(t testing.TB, ctx context.Context) string { + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "scopes", "create", + "-name", "e2e Org", + "-scope-id", "global", + "-format", "json", + ), ) require.NoError(t, output.Err, string(output.Stderr)) @@ -58,7 +60,10 @@ func CreateNewOrgCli(t testing.TB) string { newOrgId := newOrgResult.Item.Id t.Cleanup(func() { - output := e2e.RunCommand(ctx, "boundary", "scopes", "delete", "-id", newOrgId) + AuthenticateAdminCli(t, context.Background()) + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs("scopes", "delete", "-id", newOrgId), + ) require.NoError(t, output.Err, string(output.Stderr)) }) @@ -69,12 +74,14 @@ func CreateNewOrgCli(t testing.TB) 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, orgId string) string { - ctx := context.Background() - output := e2e.RunCommand(ctx, "boundary", "scopes", "create", - "-name", "e2e Project", - "-scope-id", orgId, - "-format", "json", +func CreateNewProjectCli(t testing.TB, ctx context.Context, orgId string) string { + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "scopes", "create", + "-name", "e2e Project", + "-scope-id", orgId, + "-format", "json", + ), ) require.NoError(t, output.Err, string(output.Stderr)) diff --git a/testing/internal/e2e/boundary/target.go b/testing/internal/e2e/boundary/target.go index 1a2ab415a..44ea8ba09 100644 --- a/testing/internal/e2e/boundary/target.go +++ b/testing/internal/e2e/boundary/target.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/require" ) -// CreateNewTargetApi creates a new target in boundary using the go api. +// CreateNewTargetApi creates a new target in boundary using the Go api. // Returns the id of the new target. func CreateNewTargetApi(t testing.TB, ctx context.Context, client *api.Client, projectId string, defaultPort string) string { tClient := targets.NewClient(client) @@ -29,7 +29,7 @@ func CreateNewTargetApi(t testing.TB, ctx context.Context, client *api.Client, p return newTargetId } -// AddHostSourceToTargetApi adds a host source (host set or host) to a target using the go api +// AddHostSourceToTargetApi adds a host source (host set or host) to a target using the Go api func AddHostSourceToTargetApi(t testing.TB, ctx context.Context, client *api.Client, targetId string, hostSourceId string) { tClient := targets.NewClient(client) _, err := tClient.AddHostSources(ctx, targetId, 0, @@ -41,12 +41,15 @@ func AddHostSourceToTargetApi(t testing.TB, ctx context.Context, client *api.Cli // CreateNewTargetCli creates a new target in boundary using the cli // Returns the id of the new target. -func CreateNewTargetCli(t testing.TB, projectId string, defaultPort string) string { - output := e2e.RunCommand(context.Background(), "boundary", "targets", "create", "tcp", - "-scope-id", projectId, - "-default-port", defaultPort, - "-name", "e2e Target", - "-format", "json", +func CreateNewTargetCli(t testing.TB, ctx context.Context, projectId string, defaultPort string) string { + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "targets", "create", "tcp", + "-scope-id", projectId, + "-default-port", defaultPort, + "-name", "e2e Target", + "-format", "json", + ), ) require.NoError(t, output.Err, string(output.Stderr)) var newTargetResult targets.TargetCreateResult @@ -59,10 +62,9 @@ func CreateNewTargetCli(t testing.TB, projectId string, defaultPort string) stri } // AddHostSourceToTargetCli adds a host source (host set or host) to a target using the cli -func AddHostSourceToTargetCli(t testing.TB, targetId string, hostSourceId string) { - output := e2e.RunCommand(context.Background(), "boundary", "targets", "add-host-sources", - "-id", targetId, - "-host-source", hostSourceId, +func AddHostSourceToTargetCli(t testing.TB, ctx context.Context, targetId string, hostSourceId string) { + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs("targets", "add-host-sources", "-id", targetId, "-host-source", hostSourceId), ) require.NoError(t, output.Err, string(output.Stderr)) } diff --git a/testing/internal/e2e/boundary/user.go b/testing/internal/e2e/boundary/user.go new file mode 100644 index 000000000..b018811d5 --- /dev/null +++ b/testing/internal/e2e/boundary/user.go @@ -0,0 +1,71 @@ +package boundary + +import ( + "context" + "encoding/json" + "testing" + + "github.com/hashicorp/boundary/api" + "github.com/hashicorp/boundary/api/users" + "github.com/hashicorp/boundary/testing/internal/e2e" + "github.com/stretchr/testify/require" +) + +// CreateNewUserCli creates a new user using the Go api. +// Returns the id of the new user +func CreateNewUserApi(t testing.TB, ctx context.Context, client *api.Client, scopeId string) string { + uClient := users.NewClient(client) + newUserResult, err := uClient.Create(ctx, scopeId) + require.NoError(t, err) + newUserId := newUserResult.Item.Id + t.Logf("Created User: %s", newUserId) + t.Cleanup(func() { + _, err := uClient.Delete(ctx, newUserId) + require.NoError(t, err) + }) + + return newUserId +} + +// CreateNewUserCli creates a new user using the cli. +// Returns the id of the new user +func CreateNewUserCli(t testing.TB, ctx context.Context, scopeId string) string { + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "users", "create", + "-scope-id", scopeId, + "-name", "e2e User", + "-description", "e2e User", + "-format", "json", + ), + ) + require.NoError(t, output.Err, string(output.Stderr)) + + var newUserResult users.UserCreateResult + err := json.Unmarshal(output.Stdout, &newUserResult) + require.NoError(t, err) + + newUserId := newUserResult.Item.Id + t.Cleanup(func() { + AuthenticateAdminCli(t, context.Background()) + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs("users", "delete", "-id", newUserId), + ) + require.NoError(t, output.Err, string(output.Stderr)) + }) + t.Logf("Created User: %s", newUserId) + + return newUserId +} + +// SetAccountToUserCli sets an account to a the specified user using the cli. +func SetAccountToUserCli(t testing.TB, ctx context.Context, userId string, accountId string) { + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "users", "set-accounts", + "-id", userId, + "-account", accountId, + ), + ) + require.NoError(t, output.Err, string(output.Stderr)) +} diff --git a/testing/internal/e2e/credential/vault/vault_test.go b/testing/internal/e2e/credential/vault/vault_test.go index 34774581e..a927b4e95 100644 --- a/testing/internal/e2e/credential/vault/vault_test.go +++ b/testing/internal/e2e/credential/vault/vault_test.go @@ -52,24 +52,29 @@ func TestCreateVaultCredentialStoreCli(t *testing.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) + ctx := context.Background() + boundary.AuthenticateAdminCli(t, ctx) + newOrgId := boundary.CreateNewOrgCli(t, ctx) + 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) // Configure vault - ctx := context.Background() + vaultAddr, boundaryPolicyName := vault.Setup(t) - output := e2e.RunCommand(ctx, "vault", "secrets", "enable", "-path="+c.VaultSecretPath, "kv-v2") + output := e2e.RunCommand(ctx, "vault", + e2e.WithArgs("secrets", "enable", "-path="+c.VaultSecretPath, "kv-v2"), + ) require.NoError(t, output.Err, string(output.Stderr)) t.Cleanup(func() { - output := e2e.RunCommand(ctx, "vault", "secrets", "disable", c.VaultSecretPath) + output := e2e.RunCommand(ctx, "vault", + e2e.WithArgs("secrets", "disable", c.VaultSecretPath), + ) require.NoError(t, output.Err, string(output.Stderr)) }) @@ -79,14 +84,17 @@ func TestCreateVaultCredentialStoreCli(t *testing.T) { t.Log("Created Vault Credential") // Create vault token for boundary - output = e2e.RunCommand(ctx, "vault", "token", "create", - "-no-default-policy=true", - "-policy="+boundaryPolicyName, - "-policy="+credentialPolicyName, - "-orphan=true", - "-period=20m", - "-renewable=true", - "-format=json", + output = e2e.RunCommand(ctx, "vault", + e2e.WithArgs( + "token", "create", + "-no-default-policy=true", + "-policy="+boundaryPolicyName, + "-policy="+credentialPolicyName, + "-orphan=true", + "-period=20m", + "-renewable=true", + "-format=json", + ), ) require.NoError(t, output.Err, string(output.Stderr)) var tokenCreateResult createTokenResponse @@ -96,11 +104,14 @@ func TestCreateVaultCredentialStoreCli(t *testing.T) { t.Log("Created Vault Cred Store Token") // Create a credential store - output = e2e.RunCommand(ctx, "boundary", "credential-stores", "create", "vault", - "-scope-id", newProjectId, - "-vault-address", vaultAddr, - "-vault-token", credStoreToken, - "-format", "json", + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "credential-stores", "create", "vault", + "-scope-id", newProjectId, + "-vault-address", vaultAddr, + "-vault-token", credStoreToken, + "-format", "json", + ), ) require.NoError(t, output.Err, string(output.Stderr)) var newCredentialStoreResult credentialstores.CredentialStoreCreateResult @@ -110,12 +121,15 @@ func TestCreateVaultCredentialStoreCli(t *testing.T) { t.Logf("Created Credential Store: %s", newCredentialStoreId) // Create a credential library - output = e2e.RunCommand(ctx, "boundary", "credential-libraries", "create", "vault", - "-credential-store-id", newCredentialStoreId, - "-vault-path", c.VaultSecretPath+"/data/"+secretName, - "-name", "e2e Automated Test Vault Credential Library", - "-credential-type", "ssh_private_key", - "-format", "json", + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "credential-libraries", "create", "vault", + "-credential-store-id", newCredentialStoreId, + "-vault-path", c.VaultSecretPath+"/data/"+secretName, + "-name", "e2e Automated Test Vault Credential Library", + "-credential-type", "ssh_private_key", + "-format", "json", + ), ) require.NoError(t, output.Err, string(output.Stderr)) var newCredentialLibraryResult credentiallibraries.CredentialLibraryCreateResult @@ -125,14 +139,19 @@ func TestCreateVaultCredentialStoreCli(t *testing.T) { t.Logf("Created Credential Library: %s", newCredentialLibraryId) // Add brokered credentials to target - output = e2e.RunCommand(ctx, "boundary", "targets", "add-credential-sources", - "-id", newTargetId, - "-brokered-credential-source", newCredentialLibraryId, + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "targets", "add-credential-sources", + "-id", newTargetId, + "-brokered-credential-source", newCredentialLibraryId, + ), ) require.NoError(t, output.Err, string(output.Stderr)) // Get credentials for target - output = e2e.RunCommand(ctx, "boundary", "targets", "authorize-session", "-id", newTargetId, "-format", "json") + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs("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) @@ -158,17 +177,20 @@ func TestCreateVaultCredentialStoreCli(t *testing.T) { require.NoError(t, err) // Connect to target and print host's IP address using retrieved credentials - output = e2e.RunCommand(ctx, "boundary", "connect", - "-target-id", newTargetId, - "-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", + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "connect", + "-target-id", newTargetId, + "-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)) @@ -178,9 +200,9 @@ func TestCreateVaultCredentialStoreCli(t *testing.T) { t.Log("Successfully connected to target") } -// TestCreateVaultCredentialStoreApi uses the boundary go api along with the vault cli to -// add secrets management for a target. The test sets up vault as a credential stores and creates -// a set of credentials in vault that is attached to a target. +// TestCreateVaultCredentialStoreApi uses the Go api along with the vault cli to add secrets +// management for a target. The test sets up vault as a credential stores and creates a set of +// credentials in vault that is attached to a target. func TestCreateVaultCredentialStoreApi(t *testing.T) { e2e.MaybeSkipTest(t) c, err := loadConfig() @@ -202,10 +224,14 @@ func TestCreateVaultCredentialStoreApi(t *testing.T) { // Configure vault vaultAddr, boundaryPolicyName := vault.Setup(t) - output := e2e.RunCommand(ctx, "vault", "secrets", "enable", "-path="+c.VaultSecretPath, "kv-v2") + output := e2e.RunCommand(ctx, "vault", + e2e.WithArgs("secrets", "enable", "-path="+c.VaultSecretPath, "kv-v2"), + ) require.NoError(t, output.Err, string(output.Stderr)) t.Cleanup(func() { - output := e2e.RunCommand(ctx, "vault", "secrets", "disable", c.VaultSecretPath) + output := e2e.RunCommand(ctx, "vault", + e2e.WithArgs("secrets", "disable", c.VaultSecretPath), + ) require.NoError(t, output.Err, string(output.Stderr)) }) @@ -215,14 +241,17 @@ func TestCreateVaultCredentialStoreApi(t *testing.T) { t.Log("Created Vault Credential") // Create vault token for boundary - output = e2e.RunCommand(ctx, "vault", "token", "create", - "-no-default-policy=true", - "-policy="+boundaryPolicyName, - "-policy="+credentialPolicyName, - "-orphan=true", - "-period=20m", - "-renewable=true", - "-format=json", + output = e2e.RunCommand(ctx, "vault", + e2e.WithArgs( + "token", "create", + "-no-default-policy=true", + "-policy="+boundaryPolicyName, + "-policy="+credentialPolicyName, + "-orphan=true", + "-period=20m", + "-renewable=true", + "-format=json", + ), ) require.NoError(t, output.Err, string(output.Stderr)) var tokenCreateResult createTokenResponse diff --git a/testing/internal/e2e/helpers.go b/testing/internal/e2e/helpers.go index a4f885401..a334a379a 100644 --- a/testing/internal/e2e/helpers.go +++ b/testing/internal/e2e/helpers.go @@ -23,19 +23,59 @@ type CliError struct { Status int `json:"status"` } +// Option is a func that sets optional attributes for a call. This does not need +// to be used directly, but instead option arguments are built from the +// functions in this package. WithX options set a value to that given in the +// argument; DefaultX options indicate that the value should be set to its +// default. When an API call is made options are processed in ther order they +// appear in the function call, so for a given argument X, a succession of WithX +// or DefaultX calls will result in the last call taking effect. +type Option func(*options) + +type options struct { + withArgs []string + withEnv map[string]string +} + +func getOpts(opt ...Option) options { + opts := options{} + for _, o := range opt { + if o != nil { + o(&opts) + } + } + + return opts +} + const EnvToCheckSkip = "E2E_PASSWORD_AUTH_METHOD_ID" // RunCommand executes external commands on the system. Returns the results // of running the provided command. // // RunCommand(context.Background(), "ls") -// RunCommand(context.Background(), "ls", "-al", "/path") +// RunCommand(context.Background(), "ls", WithArgs("-al", "/path")) // // CommandResult is always valid even if there is an error. -func RunCommand(ctx context.Context, name string, args ...string) *CommandResult { +func RunCommand(ctx context.Context, command string, opt ...Option) *CommandResult { + var cmd *exec.Cmd var outbuf, errbuf bytes.Buffer - cmd := exec.CommandContext(ctx, name, args...) + opts := getOpts(opt...) + + if opts.withArgs == nil { + cmd = exec.CommandContext(ctx, command) + } else { + cmd = exec.CommandContext(ctx, command, opts.withArgs...) + } + + if opts.withEnv != nil { + cmd.Env = os.Environ() + for k, v := range opts.withEnv { + cmd.Env = append(cmd.Env, k+"="+v) + } + } + cmd.Stdout = &outbuf cmd.Stderr = &errbuf @@ -55,6 +95,32 @@ func RunCommand(ctx context.Context, name string, args ...string) *CommandResult } } +// WithArgs is an option to RunCommand that allows the user to specify arguments +// for the provided command. This option can be used multiple times in one command. +func WithArgs(args ...string) Option { + return func(o *options) { + if o.withArgs == nil { + o.withArgs = args + } else { + o.withArgs = append(o.withArgs, args...) + } + } +} + +// WithEnv is an option to RunCommand that allows the user to specify environment variables +// to be set when running the command. This option can be used multiple times in one command. +// +// RunCommand(context.Background(), "ls", WithEnv("NAME", "VALUE"), WithEnv("NAME", "VALUE")) +func WithEnv(name string, value string) Option { + return func(o *options) { + if o.withEnv == nil { + o.withEnv = map[string]string{name: value} + } else { + o.withEnv[name] = value + } + } +} + // MaybeSkipTest is a check used at the start of the test to determine if the test should run func MaybeSkipTest(t testing.TB) { if _, ok := os.LookupEnv(EnvToCheckSkip); !ok { diff --git a/testing/internal/e2e/host/aws/dynamichostcatalog_test.go b/testing/internal/e2e/host/aws/dynamichostcatalog_test.go index 9cf4ea694..627ab3015 100644 --- a/testing/internal/e2e/host/aws/dynamichostcatalog_test.go +++ b/testing/internal/e2e/host/aws/dynamichostcatalog_test.go @@ -50,20 +50,23 @@ func TestCreateAwsDynamicHostCatalogCli(t *testing.T) { c, err := loadConfig() require.NoError(t, err) - boundary.AuthenticateCli(t) - newOrgId := boundary.CreateNewOrgCli(t) - newProjectId := boundary.CreateNewProjectCli(t, newOrgId) + ctx := context.Background() + boundary.AuthenticateAdminCli(t, ctx) + newOrgId := boundary.CreateNewOrgCli(t, ctx) + newProjectId := boundary.CreateNewProjectCli(t, ctx, newOrgId) // Create a dynamic host catalog - ctx := context.Background() - output := e2e.RunCommand(ctx, "boundary", "host-catalogs", "create", "plugin", - "-scope-id", newProjectId, - "-plugin-name", "aws", - "-attr", "disable_credential_rotation=true", - "-attr", "region=us-east-1", - "-secret", "access_key_id=env://E2E_AWS_ACCESS_KEY_ID", - "-secret", "secret_access_key=env://E2E_AWS_SECRET_ACCESS_KEY", - "-format", "json", + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "host-catalogs", "create", "plugin", + "-scope-id", newProjectId, + "-plugin-name", "aws", + "-attr", "disable_credential_rotation=true", + "-attr", "region=us-east-1", + "-secret", "access_key_id=env://E2E_AWS_ACCESS_KEY_ID", + "-secret", "secret_access_key=env://E2E_AWS_SECRET_ACCESS_KEY", + "-format", "json", + ), ) require.NoError(t, output.Err, string(output.Stderr)) var newHostCatalogResult hostcatalogs.HostCatalogCreateResult @@ -73,11 +76,14 @@ func TestCreateAwsDynamicHostCatalogCli(t *testing.T) { t.Logf("Created Host Catalog: %s", newHostCatalogId) // Create a host set - output = e2e.RunCommand(ctx, "boundary", "host-sets", "create", "plugin", - "-host-catalog-id", newHostCatalogId, - "-attr", "filters="+c.AwsHostSetFilter1, - "-name", "e2e Automated Test Host Set", - "-format", "json", + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "host-sets", "create", "plugin", + "-host-catalog-id", newHostCatalogId, + "-attr", "filters="+c.AwsHostSetFilter1, + "-name", "e2e Automated Test Host Set", + "-format", "json", + ), ) require.NoError(t, output.Err, string(output.Stderr)) var newHostSetResult hostsets.HostSetCreateResult @@ -92,9 +98,12 @@ func TestCreateAwsDynamicHostCatalogCli(t *testing.T) { var actualHostSetCount1 int err = backoff.RetryNotify( func() error { - output = e2e.RunCommand(ctx, "boundary", "host-sets", "read", - "-id", newHostSetId1, - "-format", "json", + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "host-sets", "read", + "-id", newHostSetId1, + "-format", "json", + ), ) if output.Err != nil { return backoff.Permanent(errors.New(string(output.Stderr))) @@ -128,11 +137,14 @@ func TestCreateAwsDynamicHostCatalogCli(t *testing.T) { assert.Equal(t, expectedHostSetCount1, actualHostSetCount1, "Numbers of hosts in host set did not match expected amount") // Create another host set - output = e2e.RunCommand(ctx, "boundary", "host-sets", "create", "plugin", - "-host-catalog-id", newHostCatalogId, - "-attr", "filters="+c.AwsHostSetFilter2, - "-name", "e2e Automated Test Host Set2", - "-format", "json", + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "host-sets", "create", "plugin", + "-host-catalog-id", newHostCatalogId, + "-attr", "filters="+c.AwsHostSetFilter2, + "-name", "e2e Automated Test Host Set2", + "-format", "json", + ), ) require.NoError(t, output.Err, string(output.Stderr)) var newHostSetResult2 hostsets.HostSetCreateResult @@ -146,9 +158,8 @@ func TestCreateAwsDynamicHostCatalogCli(t *testing.T) { var actualHostSetCount2 int err = backoff.RetryNotify( func() error { - output = e2e.RunCommand(ctx, "boundary", "host-sets", "read", - "-id", newHostSetId2, - "-format", "json", + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs("host-sets", "read", "-id", newHostSetId2, "-format", "json"), ) if output.Err != nil { return backoff.Permanent(errors.New(string(output.Stderr))) @@ -185,9 +196,8 @@ func TestCreateAwsDynamicHostCatalogCli(t *testing.T) { var actualHostCatalogCount int err = backoff.RetryNotify( func() error { - output = e2e.RunCommand(ctx, "boundary", "hosts", "list", - "-host-catalog-id", newHostCatalogId, - "-format", "json", + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs("hosts", "list", "-host-catalog-id", newHostCatalogId, "-format", "json"), ) if output.Err != nil { return backoff.Permanent(errors.New(string(output.Stderr))) @@ -218,21 +228,24 @@ func TestCreateAwsDynamicHostCatalogCli(t *testing.T) { assert.Equal(t, expectedHostCatalogCount, actualHostCatalogCount, "Numbers of hosts in host catalog did not match expected amount") // Create target - newTargetId := boundary.CreateNewTargetCli(t, newProjectId, c.TargetPort) - boundary.AddHostSourceToTargetCli(t, newTargetId, newHostSetId1) + newTargetId := boundary.CreateNewTargetCli(t, ctx, newProjectId, c.TargetPort) + boundary.AddHostSourceToTargetCli(t, ctx, newTargetId, newHostSetId1) // Connect to target - output = e2e.RunCommand(ctx, "boundary", "connect", - "-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", + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "connect", + "-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", + ), ) require.NoError(t, output.Err, string(output.Stderr)) @@ -250,9 +263,9 @@ func TestCreateAwsDynamicHostCatalogCli(t *testing.T) { require.True(t, hostIpInList, fmt.Sprintf("Connected host (%s) is not in expected list (%s)", hostIp, targetIps1)) } -// TestCreateAwsDynamicHostCatalogApi uses the boundary go api to create a host catalog with the AWS -// plugin. The test sets up an AWS dynamic host catalog, creates a host set, and sets up a target to -// the host set. +// TestCreateAwsDynamicHostCatalogApi uses the Go api to create a host catalog with the AWS plugin. +// The test sets up an AWS dynamic host catalog, creates a host set, and sets up a target to the +// host set. func TestCreateAwsDynamicHostCatalogApi(t *testing.T) { e2e.MaybeSkipTest(t) c, err := loadConfig() diff --git a/testing/internal/e2e/host/static/connect_authz_token_test.go b/testing/internal/e2e/host/static/connect_authz_token_test.go index 3b91e264d..a0a54e5ad 100644 --- a/testing/internal/e2e/host/static/connect_authz_token_test.go +++ b/testing/internal/e2e/host/static/connect_authz_token_test.go @@ -23,24 +23,27 @@ func TestConnectTargetWithAuthzTokenCli(t *testing.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) - newCredentialStoreId := boundary.CreateNewCredentialStoreStaticCli(t, newProjectId) + ctx := context.Background() + boundary.AuthenticateAdminCli(t, ctx) + newOrgId := boundary.CreateNewOrgCli(t, ctx) + 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) + newCredentialStoreId := boundary.CreateNewCredentialStoreStaticCli(t, ctx, newProjectId) // Create credentials - ctx := context.Background() - output := e2e.RunCommand(ctx, "boundary", "credentials", "create", "ssh-private-key", - "-credential-store-id", newCredentialStoreId, - "-username", c.TargetSshUser, - "-private-key", "file://"+c.TargetSshKeyPath, - "-format", "json", + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "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 @@ -50,14 +53,19 @@ func TestConnectTargetWithAuthzTokenCli(t *testing.T) { t.Logf("Created Credentials: %s", newCredentialsId) // Add credentials to target - output = e2e.RunCommand(ctx, "boundary", "targets", "add-credential-sources", - "-id", newTargetId, - "-brokered-credential-source", newCredentialsId, + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "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(ctx, "boundary", "targets", "authorize-session", "-id", newTargetId, "-format", "json") + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs("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) @@ -86,17 +94,20 @@ func TestConnectTargetWithAuthzTokenCli(t *testing.T) { require.NoError(t, err) // Connect to target and print host's IP address using retrieved credentials - output = e2e.RunCommand(ctx, "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", + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "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)) diff --git a/testing/internal/e2e/host/static/connect_ssh_test.go b/testing/internal/e2e/host/static/connect_ssh_test.go index d74a6cd57..d06871f6e 100644 --- a/testing/internal/e2e/host/static/connect_ssh_test.go +++ b/testing/internal/e2e/host/static/connect_ssh_test.go @@ -23,24 +23,27 @@ func TestConnectTargetWithSshCli(t *testing.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) - newCredentialStoreId := boundary.CreateNewCredentialStoreStaticCli(t, newProjectId) + ctx := context.Background() + boundary.AuthenticateAdminCli(t, ctx) + newOrgId := boundary.CreateNewOrgCli(t, ctx) + 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) + newCredentialStoreId := boundary.CreateNewCredentialStoreStaticCli(t, ctx, newProjectId) // Create credentials - ctx := context.Background() - output := e2e.RunCommand(ctx, "boundary", "credentials", "create", "ssh-private-key", - "-credential-store-id", newCredentialStoreId, - "-username", c.TargetSshUser, - "-private-key", "file://"+c.TargetSshKeyPath, - "-format", "json", + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "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 @@ -50,14 +53,19 @@ func TestConnectTargetWithSshCli(t *testing.T) { t.Logf("Created Credentials: %s", newCredentialsId) // Add credentials to target - output = e2e.RunCommand(ctx, "boundary", "targets", "add-credential-sources", - "-id", newTargetId, - "-brokered-credential-source", newCredentialsId, + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "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(ctx, "boundary", "targets", "authorize-session", "-id", newTargetId, "-format", "json") + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs("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) @@ -74,17 +82,20 @@ func TestConnectTargetWithSshCli(t *testing.T) { t.Log("Successfully retrieved credentials for target") // Connect to target and print host's IP address using retrieved credentials - output = e2e.RunCommand(ctx, "boundary", "connect", "ssh", - "-target-id", newTargetId, "--", - "-o", "UserKnownHostsFile=/dev/null", - "-o", "StrictHostKeyChecking=no", - "-o", "IdentitiesOnly=yes", // forces the use of the provided key + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "connect", "ssh", + "-target-id", newTargetId, "--", + "-o", "UserKnownHostsFile=/dev/null", + "-o", "StrictHostKeyChecking=no", + "-o", "IdentitiesOnly=yes", // forces the use of the provided key + ), ) require.NoError(t, output.Err, string(output.Stderr)) t.Log("Successfully connected to target") } -// TestCreateTargetWithStaticCredentialStoreApi uses the boundary go api to create a credential using +// TestCreateTargetWithStaticCredentialStoreApi uses the Go api to create a credential using // boundary's built-in credential store. The test then attaches that credential to a target. func TestCreateTargetWithStaticCredentialStoreApi(t *testing.T) { e2e.MaybeSkipTest(t) diff --git a/testing/internal/e2e/host/static/connect_test.go b/testing/internal/e2e/host/static/connect_test.go index 62c7c1e42..85a5f0258 100644 --- a/testing/internal/e2e/host/static/connect_test.go +++ b/testing/internal/e2e/host/static/connect_test.go @@ -18,29 +18,32 @@ func TestConnectTargetCli(t *testing.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) + ctx := context.Background() + boundary.AuthenticateAdminCli(t, ctx) + newOrgId := boundary.CreateNewOrgCli(t, ctx) + 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) // Connect to target and print host's IP address - ctx := context.Background() - output := e2e.RunCommand(ctx, "boundary", "connect", - "-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", + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "connect", + "-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", + ), ) require.NoError(t, output.Err, string(output.Stderr)) @@ -50,7 +53,7 @@ func TestConnectTargetCli(t *testing.T) { t.Log("Successfully connected to target") } -// TestCreateTargetApi uses the boundary go api to create a number of supporting objects +// TestCreateTargetApi uses the Go api to create a number of supporting objects // to connect to a target. This test does not connect to the target due to the complexity // when not using the cli. func TestCreateTargetApi(t *testing.T) { diff --git a/testing/internal/e2e/host/static/session_cancel_test.go b/testing/internal/e2e/host/static/session_cancel_admin_test.go similarity index 61% rename from testing/internal/e2e/host/static/session_cancel_test.go rename to testing/internal/e2e/host/static/session_cancel_admin_test.go index 249d45718..4b5aaf460 100644 --- a/testing/internal/e2e/host/static/session_cancel_test.go +++ b/testing/internal/e2e/host/static/session_cancel_admin_test.go @@ -15,47 +15,53 @@ import ( "github.com/stretchr/testify/require" ) -// TestSessionCancelCli uses the boundary cli to start and then cancel a session -func TestSessionCancelCli(t *testing.T) { +// TestSessionCancelAdminCli uses the boundary cli to start and then cancel a session +func TestSessionCancelAdminCli(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) + ctx := context.Background() + boundary.AuthenticateAdminCli(t, ctx) + newOrgId := boundary.CreateNewOrgCli(t, ctx) + 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) // Connect to target to create a session ctxCancel, cancel := context.WithCancel(context.Background()) errChan := make(chan *e2e.CommandResult) go func() { - errChan <- e2e.RunCommand(ctxCancel, "boundary", "connect", - "-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", + t.Log("Starting session...") + errChan <- e2e.RunCommand(ctxCancel, "boundary", + e2e.WithArgs( + "connect", + "-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", + ), ) }() t.Cleanup(cancel) // Get list of sessions - ctx := context.Background() var session *sessions.Session err = backoff.RetryNotify( func() error { - output := e2e.RunCommand(ctx, "boundary", "sessions", "list", "-scope-id", newProjectId, "-format", "json") + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs("sessions", "list", "-scope-id", newProjectId, "-format", "json"), + ) if output.Err != nil { return backoff.Permanent(errors.New(string(output.Stderr))) } @@ -90,10 +96,14 @@ func TestSessionCancelCli(t *testing.T) { require.Equal(t, "active", session.Status) // Cancel session - output := e2e.RunCommand(ctx, "boundary", "sessions", "cancel", "-id", session.Id) + 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", "sessions", "read", "-id", session.Id, "-format", "json") + 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) diff --git a/testing/internal/e2e/host/static/session_cancel_user_test.go b/testing/internal/e2e/host/static/session_cancel_user_test.go new file mode 100644 index 000000000..311bad08c --- /dev/null +++ b/testing/internal/e2e/host/static/session_cancel_user_test.go @@ -0,0 +1,238 @@ +package static_test + +import ( + "context" + "encoding/json" + "errors" + "testing" + "time" + + "github.com/cenkalti/backoff/v4" + "github.com/hashicorp/boundary/api/roles" + "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" +) + +// TestSessionCancelUserCli 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 TestSessionCancelUserCli(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) + 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) + newUserId := boundary.CreateNewUserCli(t, ctx, "global") + 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 e2e.CliError + err = json.Unmarshal(output.Stderr, &response) + require.NoError(t, err) + require.Equal(t, 403, response.Status) + t.Log("Successfully received an error when connecting to target as a user without permissions") + + // Create a role + boundary.AuthenticateAdminCli(t, ctx) + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "roles", "create", + "-scope-id", newProjectId, + "-name", "e2e Role", + "-format", "json", + ), + ) + require.NoError(t, output.Err, string(output.Stderr)) + var newRoleResult roles.RoleCreateResult + err = json.Unmarshal(output.Stdout, &newRoleResult) + require.NoError(t, err) + newRoleId := newRoleResult.Item.Id + t.Logf("Created Role: %s", newRoleId) + + // Add grant to role + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "roles", "add-grants", + "-id", newRoleId, + "-grant", "id=*;type=target;actions=authorize-session", + ), + ) + require.NoError(t, output.Err, string(output.Stderr)) + + // Add user to role + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "roles", "add-principals", + "-id", newRoleId, + "-principal", newUserId, + ), + ) + require.NoError(t, output.Err, string(output.Stderr)) + + // Connect to target to create a session + ctxCancel, cancel := context.WithCancel(context.Background()) + errChan := make(chan *e2e.CommandResult) + go func() { + boundary.AuthenticateCli(t, ctx, acctName, acctPassword) + t.Log("Starting session as user...") + errChan <- e2e.RunCommand(ctxCancel, "boundary", + e2e.WithArgs( + "connect", + "-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", + ), + ) + }() + t.Cleanup(cancel) + + // Get list of sessions + var session *sessions.Session + err = backoff.RetryNotify( + func() error { + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs("sessions", "list", "-scope-id", newProjectId, "-format", "json"), + ) + if output.Err != nil { + return backoff.Permanent(errors.New(string(output.Stderr))) + } + + var sessionListResult sessions.SessionListResult + err = json.Unmarshal(output.Stdout, &sessionListResult) + if err != nil { + return backoff.Permanent(err) + } + + sessionCount := len(sessionListResult.Items) + if sessionCount == 0 { + return errors.New("No items are appearing in the session list") + } + + t.Logf("Found %d session(s)", sessionCount) + if sessionCount != 1 { + return backoff.Permanent(errors.New("Only one session was expected to be found")) + } + + session = sessionListResult.Items[0] + return nil + }, + backoff.WithMaxRetries(backoff.NewConstantBackOff(3*time.Second), 5), + func(err error, td time.Duration) { + t.Logf("%s. Retrying...", err.Error()) + }, + ) + require.NoError(t, err) + assert.Equal(t, newTargetId, session.TargetId) + assert.Equal(t, newHostId, session.HostId) + require.Equal(t, "active", session.Status) + + // Cancel 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") +} + +// TestCreateUserApi uses the Go api to create a new user and add some grants to the user +func TestCreateUserApi(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) + 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) + newUserId := boundary.CreateNewUserApi(t, ctx, client, "global") + 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("Create 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) +} diff --git a/testing/internal/e2e/host/static/static_credential_store_test.go b/testing/internal/e2e/host/static/static_credential_store_test.go index c00e9d3fe..43c6dae35 100644 --- a/testing/internal/e2e/host/static/static_credential_store_test.go +++ b/testing/internal/e2e/host/static/static_credential_store_test.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "os" "testing" "time" @@ -21,18 +20,21 @@ func TestStaticCredentialStoreCli(t *testing.T) { c, err := loadConfig() require.NoError(t, err) - boundary.AuthenticateCli(t) - newOrgId := boundary.CreateNewOrgCli(t) - newProjectId := boundary.CreateNewProjectCli(t, newOrgId) - newCredentialStoreId := boundary.CreateNewCredentialStoreStaticCli(t, newProjectId) + ctx := context.Background() + boundary.AuthenticateAdminCli(t, ctx) + newOrgId := boundary.CreateNewOrgCli(t, ctx) + newProjectId := boundary.CreateNewProjectCli(t, ctx, newOrgId) + newCredentialStoreId := boundary.CreateNewCredentialStoreStaticCli(t, ctx, newProjectId) // Create ssh key credentials - ctx := context.Background() - output := e2e.RunCommand(ctx, "boundary", "credentials", "create", "ssh-private-key", - "-credential-store-id", newCredentialStoreId, - "-username", c.TargetSshUser, - "-private-key", "file://"+c.TargetSshKeyPath, - "-format", "json", + output := e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "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 keyCredentialsResult credentials.CredentialCreateResult @@ -42,12 +44,15 @@ func TestStaticCredentialStoreCli(t *testing.T) { t.Logf("Created SSH Private Key Credentials: %s", keyCredentialsId) // Create username/password credentials - os.Setenv("E2E_CREDENTIALS_PASSWORD", "password") - output = e2e.RunCommand(ctx, "boundary", "credentials", "create", "username-password", - "-credential-store-id", newCredentialStoreId, - "-username", c.TargetSshUser, - "-password", "env://E2E_CREDENTIALS_PASSWORD", - "-format", "json", + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "credentials", "create", "username-password", + "-credential-store-id", newCredentialStoreId, + "-username", c.TargetSshUser, + "-password", "env://E2E_CREDENTIALS_PASSWORD", + "-format", "json", + ), + e2e.WithEnv("E2E_CREDENTIALS_PASSWORD", "password"), ) require.NoError(t, output.Err, string(output.Stderr)) var pwCredentialsResult credentials.CredentialCreateResult @@ -57,11 +62,15 @@ func TestStaticCredentialStoreCli(t *testing.T) { t.Logf("Created Username/Password Credentials: %s", pwCredentialsId) // Delete credential store - output = e2e.RunCommand(ctx, "boundary", "credential-stores", "delete", "-id", newCredentialStoreId) + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs("credential-stores", "delete", "-id", newCredentialStoreId), + ) require.NoError(t, output.Err, string(output.Stderr)) err = backoff.RetryNotify( func() error { - output = e2e.RunCommand(ctx, "boundary", "credential-stores", "read", "-id", newCredentialStoreId, "-format", "json") + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs("credential-stores", "read", "-id", newCredentialStoreId, "-format", "json"), + ) if output.Err == nil { return fmt.Errorf("Deleted credential can still be read: '%s'", output.Stdout) } diff --git a/testing/internal/e2e/vault/vault.go b/testing/internal/e2e/vault/vault.go index 8e0247339..cb0a3b85c 100644 --- a/testing/internal/e2e/vault/vault.go +++ b/testing/internal/e2e/vault/vault.go @@ -39,12 +39,17 @@ func Setup(t testing.TB) (string, string) { require.True(t, ok) ctx := context.Background() policyName := "boundary-controller" - output := e2e.RunCommand(ctx, "vault", "policy", "write", policyName, - path.Join(path.Dir(filename), "boundary-controller-policy.hcl"), + output := e2e.RunCommand(ctx, "vault", + e2e.WithArgs( + "policy", "write", policyName, + path.Join(path.Dir(filename), "boundary-controller-policy.hcl"), + ), ) require.NoError(t, output.Err, string(output.Stderr)) t.Cleanup(func() { - output := e2e.RunCommand(ctx, "vault", "policy", "delete", policyName) + output := e2e.RunCommand(ctx, "vault", + e2e.WithArgs("policy", "delete", policyName), + ) require.NoError(t, output.Err, string(output.Stderr)) }) @@ -69,19 +74,26 @@ func CreateKvPrivateKeyCredential(t testing.TB, secretName string, secretPath st // Add policy to vault ctx := context.Background() policyName := "kv-read" - output := e2e.RunCommand(ctx, "vault", "policy", "write", policyName, kvPolicyFilePath) + output := e2e.RunCommand(ctx, "vault", + e2e.WithArgs("policy", "write", policyName, kvPolicyFilePath), + ) require.NoError(t, output.Err, string(output.Stderr)) t.Cleanup(func() { - output := e2e.RunCommand(ctx, "vault", "policy", "delete", policyName) + output := e2e.RunCommand(ctx, "vault", + e2e.WithArgs("policy", "delete", policyName), + ) require.NoError(t, output.Err, string(output.Stderr)) }) // Create secret - output = e2e.RunCommand(ctx, "vault", "kv", "put", - "-mount", secretPath, - secretName, - "username="+user, - "private_key=@"+keyPath, + output = e2e.RunCommand(ctx, "vault", + e2e.WithArgs( + "kv", "put", + "-mount", secretPath, + secretName, + "username="+user, + "private_key=@"+keyPath, + ), ) require.NoError(t, output.Err, string(output.Stderr))