diff --git a/enos/enos-scenario-e2e-database.hcl b/enos/enos-scenario-e2e-database.hcl index d9b4d9cf3..364657cbe 100644 --- a/enos/enos-scenario-e2e-database.hcl +++ b/enos/enos-scenario-e2e-database.hcl @@ -88,33 +88,11 @@ scenario "e2e_database" { } } - step "create_vault_cluster" { - module = module.vault - depends_on = [ - step.create_base_infra, - ] - - variables { - ami_id = step.create_base_infra.ami_ids["ubuntu"]["amd64"] - instance_type = var.vault_instance_type - instance_count = 1 - kms_key_arn = step.create_base_infra.kms_key_arn - storage_backend = "raft" - unseal_method = "awskms" - vault_release = { - version = var.vault_version - edition = "oss" - } - vpc_id = step.create_base_infra.vpc_id - } - } - step "run_e2e_test" { module = module.test_e2e depends_on = [ step.create_targets_with_tag, step.iam_setup, - step.create_vault_cluster, ] variables { @@ -125,8 +103,6 @@ scenario "e2e_database" { aws_access_key_id = step.iam_setup.access_key_id aws_secret_access_key = step.iam_setup.secret_access_key aws_host_set_filter1 = step.create_tag_inputs.tag_string - vault_addr = step.create_vault_cluster.instance_public_ips[0] - vault_root_token = step.create_vault_cluster.vault_root_token } } diff --git a/enos/modules/test_e2e/main.tf b/enos/modules/test_e2e/main.tf index 2321114a7..f3651ca4a 100644 --- a/enos/modules/test_e2e/main.tf +++ b/enos/modules/test_e2e/main.tf @@ -126,7 +126,7 @@ resource "enos_local_exec" "run_e2e_test" { E2E_AWS_HOST_SET_IPS2 = local.aws_host_set_ips2 } - inline = ["PATH=\"${var.local_boundary_dir}:$PATH\" go test -v ${var.test_package} -count=1 -json | tparse -follow -format plain 2>&1 | tee ${path.module}/../../test-e2e-${local.package_name}.out"] + inline = ["set -o pipefail; PATH=\"${var.local_boundary_dir}:$PATH\" go test -v ${var.test_package} -count=1 -json | tparse -follow -format plain 2>&1 | tee ${path.module}/../../test-e2e-${local.package_name}.out"] } output "test_results" { diff --git a/testing/internal/e2e/boundary/authenticate.go b/testing/internal/e2e/boundary/authenticate.go index 19f4f570b..1b06914bc 100644 --- a/testing/internal/e2e/boundary/authenticate.go +++ b/testing/internal/e2e/boundary/authenticate.go @@ -49,11 +49,11 @@ func AuthenticateAdminCli(t testing.TB, ctx context.Context) { c, err := LoadConfig() require.NoError(t, err) - AuthenticateCli(t, ctx, c.AdminLoginName, c.AdminLoginPassword) + AuthenticateCli(t, ctx, c.AuthMethodId, 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) { +func AuthenticateCli(t testing.TB, ctx context.Context, authMethodId string, loginName string, password string) { c, err := LoadConfig() require.NoError(t, err) @@ -61,7 +61,7 @@ func AuthenticateCli(t testing.TB, ctx context.Context, loginName string, passwo e2e.WithArgs( "authenticate", "password", "-addr", c.Address, - "-auth-method-id", c.AuthMethodId, + "-auth-method-id", authMethodId, "-login-name", loginName, "-password", "env://E2E_TEST_BOUNDARY_PASSWORD", ), diff --git a/testing/internal/e2e/infra/docker.go b/testing/internal/e2e/infra/docker.go index 335b69643..9eee3dbc5 100644 --- a/testing/internal/e2e/infra/docker.go +++ b/testing/internal/e2e/infra/docker.go @@ -100,7 +100,8 @@ func InitBoundaryDatabase(t testing.TB, pool *dockertest.Pool, network *dockerte } // GetDbInitInfoFromContainer extracts info from calling `boundary database init` in the specified -// container. Returns a struct containing the generated info. +// container. +// Returns a struct containing the generated info. func GetDbInitInfoFromContainer(t testing.TB, pool *dockertest.Pool, container *Container) boundary.DbInitInfo { _, err := pool.Client.WaitContainer(container.Resource.Container.ID) require.NoError(t, err) @@ -125,8 +126,8 @@ func GetDbInitInfoFromContainer(t testing.TB, pool *dockertest.Pool, container * } // StartBoundary starts a boundary container and spins up an instance of boundary using the -// specified database at postgresURI. Returns information about the container. -// Returns information about the container +// specified database at postgresURI. +// Returns information about the container. func StartBoundary(t testing.TB, pool *dockertest.Pool, network *dockertest.Network, postgresURI string) *Container { t.Log("Starting Boundary...") @@ -163,6 +164,38 @@ func StartBoundary(t testing.TB, pool *dockertest.Pool, network *dockertest.Netw } } +// StartVault starts a vault container. +// Returns information about the container. +func StartVault(t testing.TB, pool *dockertest.Pool, network *dockertest.Network) (*Container, string) { + t.Log("Starting Vault...") + + vaultToken := "boundarytok" + resource, err := pool.RunWithOptions(&dockertest.RunOptions{ + Repository: "hashicorp/vault", + Tag: "latest", + Env: []string{ + "VAULT_DEV_ROOT_TOKEN_ID=" + vaultToken, + }, + Name: "vault", + Networks: []*dockertest.Network{network}, + ExposedPorts: []string{"8200"}, + PortBindings: map[docker.Port][]docker.PortBinding{ + "8200/tcp": {{HostIP: "localhost", HostPort: "8200/tcp"}}, + }, + CapAdd: []string{"IPC_LOCK"}, + }) + require.NoError(t, err) + + uriLocalhost := "http://localhost:8200" + + return &Container{ + Resource: resource, + UriLocalhost: uriLocalhost, + UriNetwork: "http://vault:8200", + }, + vaultToken +} + // ConnectToTarget starts a boundary container and attempts to connect to the specified target. The // goal of this method is to create a session entry in the database. // Returns information about the container. diff --git a/testing/internal/e2e/tests/database/migration_test.go b/testing/internal/e2e/tests/database/migration_test.go index a779f51ec..984c30536 100644 --- a/testing/internal/e2e/tests/database/migration_test.go +++ b/testing/internal/e2e/tests/database/migration_test.go @@ -32,6 +32,7 @@ type TestEnvironment struct { Boundary *infra.Container Database *infra.Container Target *infra.Container + Vault *infra.Container DbInitInfo boundary.DbInitInfo } @@ -70,13 +71,19 @@ func setupEnvironment(t testing.TB, ctx context.Context, c *config) TestEnvironm require.NoError(t, err) err = pool.Client.Ping() require.NoError(t, err) + pool.MaxWait = 10 * time.Second - // This ensures that the latest Boundary image is used + // This ensures that the latest images are used err = pool.Client.PullImage(docker.PullImageOptions{ Repository: "hashicorp/boundary", Tag: "latest", }, docker.AuthConfiguration{}) require.NoError(t, err) + err = pool.Client.PullImage(docker.PullImageOptions{ + Repository: "hashicorp/vault", + Tag: "latest", + }, docker.AuthConfiguration{}) + require.NoError(t, err) // Set up docker network network, err := pool.CreateNetwork(t.Name()) @@ -85,13 +92,34 @@ func setupEnvironment(t testing.TB, ctx context.Context, c *config) TestEnvironm require.NoError(t, pool.RemoveNetwork(network)) }) + // Start Vault + v, vaultToken := infra.StartVault(t, pool, network) + t.Cleanup(func() { + pool.Purge(v.Resource) + }) + os.Setenv("VAULT_ADDR", v.UriLocalhost) + os.Setenv("VAULT_TOKEN", vaultToken) + t.Log("Waiting for Vault to finish loading...") + err = pool.Retry(func() error { + response, err := http.Get(v.UriLocalhost) + if err != nil { + t.Logf("Could not access Vault URL: %s. Retrying...", err.Error()) + return err + } + + if response.StatusCode != http.StatusOK { + return fmt.Errorf("Could not connect to %s. Status Code: %d", v.UriLocalhost, response.StatusCode) + } + + return nil + }) + require.NoError(t, err) + // Start a Boundary database and wait until it's ready db := infra.StartBoundaryDatabase(t, pool, network) t.Cleanup(func() { pool.Purge(db.Resource) }) - - pool.MaxWait = 10 * time.Second t.Log("Waiting for database to load...") err = pool.Retry(func() error { db, err := sql.Open("pgx", db.UriLocalhost) @@ -120,6 +148,7 @@ func setupEnvironment(t testing.TB, ctx context.Context, c *config) TestEnvironm t.Cleanup(func() { pool.Purge(b.Resource) }) + os.Setenv("BOUNDARY_ADDR", b.UriLocalhost) buf := bytes.NewBuffer(nil) ebuf := bytes.NewBuffer(nil) @@ -153,20 +182,16 @@ func setupEnvironment(t testing.TB, ctx context.Context, c *config) TestEnvironm Boundary: b, Database: db, Target: target, + Vault: v, DbInitInfo: dbInitInfo, } } func populateBoundaryDatabase(t testing.TB, ctx context.Context, c *config, te TestEnvironment) { - os.Setenv("BOUNDARY_ADDR", te.Boundary.UriLocalhost) - os.Setenv("E2E_PASSWORD_AUTH_METHOD_ID", te.DbInitInfo.AuthMethod.AuthMethodId) - os.Setenv("E2E_PASSWORD_ADMIN_LOGIN_NAME", te.DbInitInfo.AuthMethod.LoginName) - os.Setenv("E2E_PASSWORD_ADMIN_PASSWORD", te.DbInitInfo.AuthMethod.Password) - // Create resources for target. Uses the local CLI so that these methods can be reused. // While the CLI version used won't necessarily match the controller version, it should be (and is // supposed to be) backwards ompatible - boundary.AuthenticateAdminCli(t, ctx) + boundary.AuthenticateCli(t, ctx, te.DbInitInfo.AuthMethod.AuthMethodId, te.DbInitInfo.AuthMethod.LoginName, te.DbInitInfo.AuthMethod.Password) newOrgId := boundary.CreateNewOrgCli(t, ctx) newProjectId := boundary.CreateNewProjectCli(t, ctx, newOrgId) newHostCatalogId := boundary.CreateNewHostCatalogCli(t, ctx, newProjectId) @@ -189,31 +214,14 @@ func populateBoundaryDatabase(t testing.TB, ctx context.Context, c *config, te T boundary.AddCredentialSourceToTargetCli(t, ctx, newTargetId, newCredentialsId) // Create vault credentials - vaultAddr, boundaryPolicyName, kvPolicyFilePath := vault.Setup(t) - t.Cleanup(func() { - output := e2e.RunCommand(ctx, "vault", - e2e.WithArgs("policy", "delete", boundaryPolicyName), - ) - require.NoError(t, output.Err, string(output.Stderr)) - }) + _, boundaryPolicyName, kvPolicyFilePath := vault.Setup(t) 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", - e2e.WithArgs("secrets", "disable", c.VaultSecretPath), - ) - require.NoError(t, output.Err, string(output.Stderr)) - }) + privateKeySecretName := vault.CreateKvPrivateKeyCredential(t, c.VaultSecretPath, c.TargetSshUser, c.TargetSshKeyPath, kvPolicyFilePath) kvPolicyName := vault.WritePolicy(t, ctx, kvPolicyFilePath) - t.Cleanup(func() { - output := e2e.RunCommand(ctx, "vault", - e2e.WithArgs("policy", "delete", kvPolicyName), - ) - require.NoError(t, output.Err, string(output.Stderr)) - }) t.Log("Created Vault Credential") output = e2e.RunCommand(ctx, "vault", e2e.WithArgs( @@ -233,7 +241,7 @@ func populateBoundaryDatabase(t testing.TB, ctx context.Context, c *config, te T require.NoError(t, err) credStoreToken := tokenCreateResult.Auth.Client_Token t.Log("Created Vault Cred Store Token") - newVaultCredentialStoreId := boundary.CreateNewCredentialStoreVaultCli(t, ctx, newProjectId, vaultAddr, credStoreToken) + newVaultCredentialStoreId := boundary.CreateNewCredentialStoreVaultCli(t, ctx, newProjectId, te.Vault.UriNetwork, credStoreToken) output = e2e.RunCommand(ctx, "boundary", e2e.WithArgs( "credential-libraries", "create", "vault", diff --git a/testing/internal/e2e/tests/static/session_cancel_group_test.go b/testing/internal/e2e/tests/static/session_cancel_group_test.go index 9f86fb6b3..c7a3c6b2c 100644 --- a/testing/internal/e2e/tests/static/session_cancel_group_test.go +++ b/testing/internal/e2e/tests/static/session_cancel_group_test.go @@ -29,6 +29,8 @@ func TestCliSessionCancelGroup(t *testing.T) { e2e.MaybeSkipTest(t) c, err := loadConfig() require.NoError(t, err) + bc, err := boundary.LoadConfig() + require.NoError(t, err) ctx := context.Background() boundary.AuthenticateAdminCli(t, ctx) @@ -66,7 +68,7 @@ func TestCliSessionCancelGroup(t *testing.T) { boundary.SetAccountToUserCli(t, ctx, newUserId, newAccountId) // Try to connect to the target as a user without permissions - boundary.AuthenticateCli(t, ctx, acctName, acctPassword) + boundary.AuthenticateCli(t, ctx, bc.AuthMethodId, acctName, acctPassword) output := e2e.RunCommand(ctx, "boundary", e2e.WithArgs( "connect", diff --git a/testing/internal/e2e/tests/static/session_cancel_user_test.go b/testing/internal/e2e/tests/static/session_cancel_user_test.go index ae381bed7..62868eae3 100644 --- a/testing/internal/e2e/tests/static/session_cancel_user_test.go +++ b/testing/internal/e2e/tests/static/session_cancel_user_test.go @@ -28,6 +28,8 @@ func TestCliSessionCancelUser(t *testing.T) { e2e.MaybeSkipTest(t) c, err := loadConfig() require.NoError(t, err) + bc, err := boundary.LoadConfig() + require.NoError(t, err) ctx := context.Background() boundary.AuthenticateAdminCli(t, ctx) @@ -65,7 +67,7 @@ func TestCliSessionCancelUser(t *testing.T) { boundary.SetAccountToUserCli(t, ctx, newUserId, newAccountId) // Try to connect to the target as a user without permissions - boundary.AuthenticateCli(t, ctx, acctName, acctPassword) + boundary.AuthenticateCli(t, ctx, bc.AuthMethodId, acctName, acctPassword) output := e2e.RunCommand(ctx, "boundary", e2e.WithArgs( "connect",