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:
1 parent
cabe362534
commit
8ad861f426
7 files changed
+83
-62
No files matched your search
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
),
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in new issue
Block a user