test(e2e): Update migration test to use vault docker container (#2909)

* fix(enos): Make sure enos reports test as failure

After updating this command to save off the output from running `go test`, enos would not report when tests failed. This was due to the extra pipe hiding the exit status of the prior commands. Adding this option should return the status of the last command to exit with a non-zero status.

* doc(e2e): Fix comments

* refact(e2e): Update AuthenticateCli to accept auth method id

* refact(e2e/migration): Use docker to set up vault instead of enos

* refact(e2e/migration): Adjust where environment variables are set
This commit is contained in:
Michael Li authored and GitHub committed 2023-02-07 14:00:05 -05:00
1 parent cabe362534
commit 8ad861f426
7 files changed
+83 -62

No files matched your search

-24
View File
@@ -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
}
}
+1 -1
View File
@@ -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" {
@@ -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",
),
+36 -3
View File
@@ -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.
@@ -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",
@@ -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",
@@ -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",