Files
threshold/testing/internal/e2e/tests/static_with_vault/connect_test.go
T
Michael LiandJohan Brandhorst-Satzkorn 45171a3f56 refact(e2e): Changes to support an automated migration test (#2676)
* refact(e2e): Move cleanup steps into each test

The migration test needed to create some resources, but doesn't care about cleaning up because the test would take care of spinning down the docker container that it's using. To maintain flexibility going forward, we'll establish that tests are responsible for cleaning up (rather than the methods they use)

* refact(e2e): Use new env var for skip check

Currently, the e2e tests use the E2E_PASSWORD_AUTH_METHOD_ID environment variable to determine if the test should be skipped. However, the new migration test does not require a pre-existing boundary cluster and would not have this environment variable. As a result, we needed an alternative way to check if an e2e test should be skipped when running tests in ci.

* refact(e2e): Create more common boundary methods

* fix(e2e): Set to string value

Co-authored-by: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
2022-12-06 15:59:17 -05:00

172 lines
6.2 KiB
Go

package static_with_vault_test
import (
"context"
"encoding/json"
"fmt"
"os"
"strings"
"testing"
"github.com/hashicorp/boundary/api/credentiallibraries"
"github.com/hashicorp/boundary/api/targets"
"github.com/hashicorp/boundary/testing/internal/e2e"
"github.com/hashicorp/boundary/testing/internal/e2e/boundary"
"github.com/hashicorp/boundary/testing/internal/e2e/vault"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TestCliVaultConnectTarget uses the boundary and vault clis to add secrets management
// for a target. The test sets up vault as a credential store, creates a set of credentials
// in vault to be attached to a target, and attempts to connect to that target using those
// credentials.
func TestCliVaultConnectTarget(t *testing.T) {
e2e.MaybeSkipTest(t)
c, err := loadConfig()
require.NoError(t, err)
ctx := context.Background()
boundary.AuthenticateAdminCli(t, ctx)
newOrgId := boundary.CreateNewOrgCli(t, ctx)
t.Cleanup(func() {
ctx := context.Background()
boundary.AuthenticateAdminCli(t, ctx)
output := e2e.RunCommand(ctx, "boundary", e2e.WithArgs("scopes", "delete", "-id", newOrgId))
require.NoError(t, output.Err, string(output.Stderr))
})
newProjectId := boundary.CreateNewProjectCli(t, ctx, newOrgId)
newHostCatalogId := boundary.CreateNewHostCatalogCli(t, ctx, newProjectId)
newHostSetId := boundary.CreateNewHostSetCli(t, ctx, newHostCatalogId)
newHostId := boundary.CreateNewHostCli(t, ctx, newHostCatalogId, c.TargetIp)
boundary.AddHostToHostSetCli(t, ctx, newHostSetId, newHostId)
newTargetId := boundary.CreateNewTargetCli(t, ctx, newProjectId, c.TargetPort)
boundary.AddHostSourceToTargetCli(t, ctx, newTargetId, newHostSetId)
// Configure vault
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))
})
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))
})
// Create credential in vault
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")
// Create vault token for boundary
output = e2e.RunCommand(ctx, "vault",
e2e.WithArgs(
"token", "create",
"-no-default-policy=true",
"-policy="+boundaryPolicyName,
"-policy="+kvPolicyName,
"-orphan=true",
"-period=20m",
"-renewable=true",
"-format=json",
),
)
require.NoError(t, output.Err, string(output.Stderr))
var tokenCreateResult vault.CreateTokenResponse
err = json.Unmarshal(output.Stdout, &tokenCreateResult)
require.NoError(t, err)
credStoreToken := tokenCreateResult.Auth.Client_Token
t.Log("Created Vault Cred Store Token")
// Create a credential store
newCredentialStoreId := boundary.CreateNewCredentialStoreVaultCli(t, ctx, newProjectId, vaultAddr, credStoreToken)
// Create a credential library
output = e2e.RunCommand(ctx, "boundary",
e2e.WithArgs(
"credential-libraries", "create", "vault",
"-credential-store-id", newCredentialStoreId,
"-vault-path", c.VaultSecretPath+"/data/"+privateKeySecretName,
"-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
err = json.Unmarshal(output.Stdout, &newCredentialLibraryResult)
require.NoError(t, err)
newCredentialLibraryId := newCredentialLibraryResult.Item.Id
t.Logf("Created Credential Library: %s", newCredentialLibraryId)
// Add brokered credentials to target
boundary.AddCredentialSourceToTargetCli(t, ctx, newTargetId, newCredentialLibraryId)
// Get credentials for target
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)
require.NoError(t, err)
newSessionAuthorization := newSessionAuthorizationResult.Item
retrievedUser := fmt.Sprintf("%s", newSessionAuthorization.Credentials[0].Credential["username"])
retrievedKey := fmt.Sprintf("%s", newSessionAuthorization.Credentials[0].Credential["private_key"])
assert.Equal(t, c.TargetSshUser, retrievedUser)
k, err := os.ReadFile(c.TargetSshKeyPath)
require.NoError(t, err)
require.Equal(t, string(k), retrievedKey)
t.Log("Successfully retrieved credentials for target")
// Create key file
retrievedKeyPath := fmt.Sprintf("%s/%s", t.TempDir(), "target_private_key.pem")
f, err := os.Create(retrievedKeyPath)
require.NoError(t, err)
_, err = f.WriteString(retrievedKey)
require.NoError(t, err)
err = os.Chmod(retrievedKeyPath, 0o400)
require.NoError(t, err)
// Connect to target and print host's IP address using retrieved credentials
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))
parts := strings.Fields(string(output.Stdout))
hostIp := parts[len(parts)-1]
require.Equal(t, c.TargetIp, hostIp, "SSH session did not return expected output")
t.Log("Successfully connected to target")
}