From ae28bf7838704a1b2fc171b018229c0e920128ca Mon Sep 17 00:00:00 2001 From: Michael Li Date: Tue, 8 Nov 2022 16:45:55 -0500 Subject: [PATCH] test(e2e): Update test to also use a username/password credential in vault (#2595) * test(e2e): Add test that uses a vault username/password * refact(e2e): Use go:embed for policy file --- .../connect_authz_token_test.go | 10 +- .../static_with_vault/connect_ssh_test.go | 10 +- .../tests/static_with_vault/connect_test.go | 10 +- .../credential_store_test.go | 153 +++++++++++++----- .../boundary-controller-policy.hcl | 0 testing/internal/e2e/vault/vault.go | 120 +++++++++----- 6 files changed, 205 insertions(+), 98 deletions(-) rename testing/internal/e2e/vault/{ => testdata}/boundary-controller-policy.hcl (100%) diff --git a/testing/internal/e2e/tests/static_with_vault/connect_authz_token_test.go b/testing/internal/e2e/tests/static_with_vault/connect_authz_token_test.go index 5892f548e6..a027a4e52f 100644 --- a/testing/internal/e2e/tests/static_with_vault/connect_authz_token_test.go +++ b/testing/internal/e2e/tests/static_with_vault/connect_authz_token_test.go @@ -38,7 +38,7 @@ func TestCliVaultConnectTargetWithAuthzToken(t *testing.T) { boundary.AddHostSourceToTargetCli(t, ctx, newTargetId, newHostSetId) // Configure vault - vaultAddr, boundaryPolicyName := vault.Setup(t) + vaultAddr, boundaryPolicyName, kvPolicyFilePath := vault.Setup(t) output := e2e.RunCommand(ctx, "vault", e2e.WithArgs("secrets", "enable", "-path="+c.VaultSecretPath, "kv-v2"), ) @@ -51,8 +51,8 @@ func TestCliVaultConnectTargetWithAuthzToken(t *testing.T) { }) // Create credential in vault - secretName := "TestCreateVaultCredentialStoreCli" - credentialPolicyName := vault.CreateKvPrivateKeyCredential(t, secretName, c.VaultSecretPath, c.TargetSshUser, c.TargetSshKeyPath) + privateKeySecretName := vault.CreateKvPrivateKeyCredential(t, c.VaultSecretPath, c.TargetSshUser, c.TargetSshKeyPath, kvPolicyFilePath) + kvPolicyName := vault.WritePolicy(t, ctx, kvPolicyFilePath) t.Log("Created Vault Credential") // Create vault token for boundary @@ -61,7 +61,7 @@ func TestCliVaultConnectTargetWithAuthzToken(t *testing.T) { "token", "create", "-no-default-policy=true", "-policy="+boundaryPolicyName, - "-policy="+credentialPolicyName, + "-policy="+kvPolicyName, "-orphan=true", "-period=20m", "-renewable=true", @@ -97,7 +97,7 @@ func TestCliVaultConnectTargetWithAuthzToken(t *testing.T) { e2e.WithArgs( "credential-libraries", "create", "vault", "-credential-store-id", newCredentialStoreId, - "-vault-path", c.VaultSecretPath+"/data/"+secretName, + "-vault-path", c.VaultSecretPath+"/data/"+privateKeySecretName, "-name", "e2e Automated Test Vault Credential Library", "-credential-type", "ssh_private_key", "-format", "json", diff --git a/testing/internal/e2e/tests/static_with_vault/connect_ssh_test.go b/testing/internal/e2e/tests/static_with_vault/connect_ssh_test.go index cc6cb38344..55057c82d1 100644 --- a/testing/internal/e2e/tests/static_with_vault/connect_ssh_test.go +++ b/testing/internal/e2e/tests/static_with_vault/connect_ssh_test.go @@ -38,7 +38,7 @@ func TestCliVaultConnectTargetWithSsh(t *testing.T) { boundary.AddHostSourceToTargetCli(t, ctx, newTargetId, newHostSetId) // Configure vault - vaultAddr, boundaryPolicyName := vault.Setup(t) + vaultAddr, boundaryPolicyName, kvPolicyFilePath := vault.Setup(t) output := e2e.RunCommand(ctx, "vault", e2e.WithArgs("secrets", "enable", "-path="+c.VaultSecretPath, "kv-v2"), ) @@ -51,8 +51,8 @@ func TestCliVaultConnectTargetWithSsh(t *testing.T) { }) // Create credential in vault - secretName := "TestCreateVaultCredentialStoreCli" - credentialPolicyName := vault.CreateKvPrivateKeyCredential(t, secretName, c.VaultSecretPath, c.TargetSshUser, c.TargetSshKeyPath) + privateKeySecretName := vault.CreateKvPrivateKeyCredential(t, c.VaultSecretPath, c.TargetSshUser, c.TargetSshKeyPath, kvPolicyFilePath) + kvPolicyName := vault.WritePolicy(t, ctx, kvPolicyFilePath) t.Log("Created Vault Credential") // Create vault token for boundary @@ -61,7 +61,7 @@ func TestCliVaultConnectTargetWithSsh(t *testing.T) { "token", "create", "-no-default-policy=true", "-policy="+boundaryPolicyName, - "-policy="+credentialPolicyName, + "-policy="+kvPolicyName, "-orphan=true", "-period=20m", "-renewable=true", @@ -97,7 +97,7 @@ func TestCliVaultConnectTargetWithSsh(t *testing.T) { e2e.WithArgs( "credential-libraries", "create", "vault", "-credential-store-id", newCredentialStoreId, - "-vault-path", c.VaultSecretPath+"/data/"+secretName, + "-vault-path", c.VaultSecretPath+"/data/"+privateKeySecretName, "-name", "e2e Automated Test Vault Credential Library", "-credential-type", "ssh_private_key", "-format", "json", diff --git a/testing/internal/e2e/tests/static_with_vault/connect_test.go b/testing/internal/e2e/tests/static_with_vault/connect_test.go index 6a81a1863c..d600822a63 100644 --- a/testing/internal/e2e/tests/static_with_vault/connect_test.go +++ b/testing/internal/e2e/tests/static_with_vault/connect_test.go @@ -45,7 +45,7 @@ func TestCliVaultConnectTarget(t *testing.T) { boundary.AddHostSourceToTargetCli(t, ctx, newTargetId, newHostSetId) // Configure vault - vaultAddr, boundaryPolicyName := vault.Setup(t) + vaultAddr, boundaryPolicyName, kvPolicyFilePath := vault.Setup(t) output := e2e.RunCommand(ctx, "vault", e2e.WithArgs("secrets", "enable", "-path="+c.VaultSecretPath, "kv-v2"), ) @@ -58,8 +58,8 @@ func TestCliVaultConnectTarget(t *testing.T) { }) // Create credential in vault - secretName := "TestCreateVaultCredentialStoreCli" - credentialPolicyName := vault.CreateKvPrivateKeyCredential(t, secretName, c.VaultSecretPath, c.TargetSshUser, c.TargetSshKeyPath) + privateKeySecretName := vault.CreateKvPrivateKeyCredential(t, c.VaultSecretPath, c.TargetSshUser, c.TargetSshKeyPath, kvPolicyFilePath) + kvPolicyName := vault.WritePolicy(t, ctx, kvPolicyFilePath) t.Log("Created Vault Credential") // Create vault token for boundary @@ -68,7 +68,7 @@ func TestCliVaultConnectTarget(t *testing.T) { "token", "create", "-no-default-policy=true", "-policy="+boundaryPolicyName, - "-policy="+credentialPolicyName, + "-policy="+kvPolicyName, "-orphan=true", "-period=20m", "-renewable=true", @@ -104,7 +104,7 @@ func TestCliVaultConnectTarget(t *testing.T) { e2e.WithArgs( "credential-libraries", "create", "vault", "-credential-store-id", newCredentialStoreId, - "-vault-path", c.VaultSecretPath+"/data/"+secretName, + "-vault-path", c.VaultSecretPath+"/data/"+privateKeySecretName, "-name", "e2e Automated Test Vault Credential Library", "-credential-type", "ssh_private_key", "-format", "json", diff --git a/testing/internal/e2e/tests/static_with_vault/credential_store_test.go b/testing/internal/e2e/tests/static_with_vault/credential_store_test.go index 8fcde0bbdd..b87066d13e 100644 --- a/testing/internal/e2e/tests/static_with_vault/credential_store_test.go +++ b/testing/internal/e2e/tests/static_with_vault/credential_store_test.go @@ -36,7 +36,7 @@ func TestCliVaultCredentialStore(t *testing.T) { boundary.AddHostSourceToTargetCli(t, ctx, newTargetId, newHostSetId) // Configure vault - vaultAddr, boundaryPolicyName := vault.Setup(t) + vaultAddr, boundaryPolicyName, kvPolicyFilePath := vault.Setup(t) output := e2e.RunCommand(ctx, "vault", e2e.WithArgs("secrets", "enable", "-path="+c.VaultSecretPath, "kv-v2"), ) @@ -48,10 +48,11 @@ func TestCliVaultCredentialStore(t *testing.T) { require.NoError(t, output.Err, string(output.Stderr)) }) - // Create credential in vault - secretName := "TestCreateVaultCredentialStoreCli" - credentialPolicyName := vault.CreateKvPrivateKeyCredential(t, secretName, c.VaultSecretPath, c.TargetSshUser, c.TargetSshKeyPath) - t.Log("Created Vault Credential") + // Create credentials in vault + privateKeySecretName := vault.CreateKvPrivateKeyCredential(t, c.VaultSecretPath, c.TargetSshUser, c.TargetSshKeyPath, kvPolicyFilePath) + passwordSecretName, password := vault.CreateKvPasswordCredential(t, c.VaultSecretPath, c.TargetSshUser, kvPolicyFilePath) + kvPolicyName := vault.WritePolicy(t, ctx, kvPolicyFilePath) + t.Log("Created Vault Credentials") // Create vault token for boundary output = e2e.RunCommand(ctx, "vault", @@ -59,7 +60,7 @@ func TestCliVaultCredentialStore(t *testing.T) { "token", "create", "-no-default-policy=true", "-policy="+boundaryPolicyName, - "-policy="+credentialPolicyName, + "-policy="+kvPolicyName, "-orphan=true", "-period=20m", "-renewable=true", @@ -90,13 +91,13 @@ func TestCliVaultCredentialStore(t *testing.T) { newCredentialStoreId := newCredentialStoreResult.Item.Id t.Logf("Created Credential Store: %s", newCredentialStoreId) - // Create a credential library + // Create a credential library for the private key 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", + "-vault-path", c.VaultSecretPath+"/data/"+privateKeySecretName, + "-name", "e2e Automated Test Vault Credential Library - Private Key", "-credential-type", "ssh_private_key", "-format", "json", ), @@ -105,26 +106,52 @@ func TestCliVaultCredentialStore(t *testing.T) { 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) + newPrivateKeyCredentialLibraryId := newCredentialLibraryResult.Item.Id + t.Logf("Created Credential Library: %s", newPrivateKeyCredentialLibraryId) + + // Create a credential library for the password + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "credential-libraries", "create", "vault", + "-credential-store-id", newCredentialStoreId, + "-vault-path", c.VaultSecretPath+"/data/"+passwordSecretName, + "-name", "e2e Automated Test Vault Credential Library - Password", + "-credential-type", "username_password", + "-format", "json", + ), + ) + require.NoError(t, output.Err, string(output.Stderr)) + err = json.Unmarshal(output.Stdout, &newCredentialLibraryResult) + require.NoError(t, err) + newPasswordCredentialLibraryId := newCredentialLibraryResult.Item.Id + t.Logf("Created Credential Library: %s", newPasswordCredentialLibraryId) // Get credentials for target (expect empty) output = e2e.RunCommand(ctx, "boundary", e2e.WithArgs("targets", "authorize-session", "-id", newTargetId, "-format", "json"), ) require.NoError(t, output.Err, string(output.Stderr)) - t.Logf("%s", output.Stdout) var newSessionAuthorizationResult targets.SessionAuthorizationResult err = json.Unmarshal(output.Stdout, &newSessionAuthorizationResult) require.NoError(t, err) require.True(t, newSessionAuthorizationResult.Item.Credentials == nil) - // Add brokered credentials to target + // Add private key brokered credentials to target output = e2e.RunCommand(ctx, "boundary", e2e.WithArgs( "targets", "add-credential-sources", "-id", newTargetId, - "-brokered-credential-source", newCredentialLibraryId, + "-brokered-credential-source", newPrivateKeyCredentialLibraryId, + ), + ) + require.NoError(t, output.Err, string(output.Stderr)) + + // Add password brokered credentials to target + output = e2e.RunCommand(ctx, "boundary", + e2e.WithArgs( + "targets", "add-credential-sources", + "-id", newTargetId, + "-brokered-credential-source", newPasswordCredentialLibraryId, ), ) require.NoError(t, output.Err, string(output.Stderr)) @@ -138,14 +165,26 @@ func TestCliVaultCredentialStore(t *testing.T) { 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) + require.Len(t, newSessionAuthorization.Credentials, 2) - k, err := os.ReadFile(c.TargetSshKeyPath) - require.NoError(t, err) - require.Equal(t, string(k), retrievedKey) - t.Log("Successfully retrieved credentials for target") + for _, v := range newSessionAuthorization.Credentials { + if v.CredentialSource.CredentialType == "ssh_private_key" { + retrievedUser := v.Credential["username"].(string) + retrievedKey := v.Credential["private_key"].(string) + assert.Equal(t, c.TargetSshUser, retrievedUser) + + keyData, err := os.ReadFile(c.TargetSshKeyPath) + require.NoError(t, err) + require.Equal(t, string(keyData), retrievedKey) + t.Log("Successfully retrieved private key credentials for target") + } else if v.CredentialSource.CredentialType == "username_password" { + retrievedUser := v.Credential["username"].(string) + retrievedPassword := v.Credential["password"].(string) + assert.Equal(t, c.TargetSshUser, retrievedUser) + assert.Equal(t, password, retrievedPassword) + t.Log("Successfully retrieved password credentials for target") + } + } } // TestApiVaultCredentialStore uses the Go api to perform a number of credential store operations @@ -169,8 +208,7 @@ func TestApiVaultCredentialStore(t *testing.T) { boundary.AddHostSourceToTargetApi(t, ctx, client, newTargetId, newHostSetId) // Configure vault - vaultAddr, boundaryPolicyName := vault.Setup(t) - + vaultAddr, boundaryPolicyName, kvPolicyFilePath := vault.Setup(t) output := e2e.RunCommand(ctx, "vault", e2e.WithArgs("secrets", "enable", "-path="+c.VaultSecretPath, "kv-v2"), ) @@ -183,9 +221,10 @@ func TestApiVaultCredentialStore(t *testing.T) { }) // Create credential in vault - secretName := "TestCreateVaultCredentialStoreCli" - credentialPolicyName := vault.CreateKvPrivateKeyCredential(t, secretName, c.VaultSecretPath, c.TargetSshUser, c.TargetSshKeyPath) - t.Log("Created Vault Credential") + privateKeySecretName := vault.CreateKvPrivateKeyCredential(t, c.VaultSecretPath, c.TargetSshUser, c.TargetSshKeyPath, kvPolicyFilePath) + passwordSecretName, password := vault.CreateKvPasswordCredential(t, c.VaultSecretPath, c.TargetSshUser, kvPolicyFilePath) + kvPolicyName := vault.WritePolicy(t, ctx, kvPolicyFilePath) + t.Log("Created Vault Credentials") // Create vault token for boundary output = e2e.RunCommand(ctx, "vault", @@ -193,7 +232,7 @@ func TestApiVaultCredentialStore(t *testing.T) { "token", "create", "-no-default-policy=true", "-policy="+boundaryPolicyName, - "-policy="+credentialPolicyName, + "-policy="+kvPolicyName, "-orphan=true", "-period=20m", "-renewable=true", @@ -217,20 +256,36 @@ func TestApiVaultCredentialStore(t *testing.T) { newCredentialStoreId := newCredentialStoreResult.Item.Id t.Logf("Created Credential Store: %s", newCredentialStoreId) - // Create a credential library + // Create a credential library for the private key clClient := credentiallibraries.NewClient(client) newCredentialLibraryResult, err := clClient.Create(ctx, newCredentialStoreId, - credentiallibraries.WithVaultCredentialLibraryPath(c.VaultSecretPath+"/data/"+secretName), + credentiallibraries.WithVaultCredentialLibraryPath(c.VaultSecretPath+"/data/"+privateKeySecretName), credentiallibraries.WithCredentialType("ssh_private_key"), ) require.NoError(t, err) - newCredentialLibraryId := newCredentialLibraryResult.Item.Id - t.Logf("Created Credential Library: %s", newCredentialLibraryId) + newPrivateKeyCredentialLibraryId := newCredentialLibraryResult.Item.Id + t.Logf("Created Credential Library: %s", newPrivateKeyCredentialLibraryId) + + // Create a credential library for the password + newCredentialLibraryResult, err = clClient.Create(ctx, newCredentialStoreId, + credentiallibraries.WithVaultCredentialLibraryPath(c.VaultSecretPath+"/data/"+passwordSecretName), + credentiallibraries.WithCredentialType("username_password"), + ) + require.NoError(t, err) + newPasswordCredentialLibraryId := newCredentialLibraryResult.Item.Id + t.Logf("Created Credential Library: %s", newPasswordCredentialLibraryId) - // Add brokered credentials to target + // Add private key brokered credentials to target tClient := targets.NewClient(client) _, err = tClient.AddCredentialSources(ctx, newTargetId, 0, - targets.WithBrokeredCredentialSourceIds([]string{newCredentialLibraryId}), + targets.WithBrokeredCredentialSourceIds([]string{newPrivateKeyCredentialLibraryId}), + targets.WithAutomaticVersioning(true), + ) + require.NoError(t, err) + + // Add password brokered credentials to target + _, err = tClient.AddCredentialSources(ctx, newTargetId, 0, + targets.WithBrokeredCredentialSourceIds([]string{newPasswordCredentialLibraryId}), targets.WithAutomaticVersioning(true), ) require.NoError(t, err) @@ -239,15 +294,27 @@ func TestApiVaultCredentialStore(t *testing.T) { newSessionAuthorizationResult, err := tClient.AuthorizeSession(ctx, newTargetId) require.NoError(t, err) newSessionAuthorization := newSessionAuthorizationResult.Item - retrievedUser, ok := newSessionAuthorization.Credentials[0].Credential["username"].(string) - require.True(t, ok) - assert.Equal(t, c.TargetSshUser, retrievedUser) + require.Len(t, newSessionAuthorization.Credentials, 2) - retrievedKey, ok := newSessionAuthorization.Credentials[0].Credential["private_key"].(string) - require.True(t, ok) - k, err := os.ReadFile(c.TargetSshKeyPath) - require.NoError(t, err) - keysMatch := string(k) == retrievedKey // This is done to prevent printing out key info - require.True(t, keysMatch, "Key retrieved from vault does not match expected value") - t.Log("Successfully retrieved credentials for target") + for _, v := range newSessionAuthorization.Credentials { + if v.CredentialSource.CredentialType == "ssh_private_key" { + retrievedUser, ok := v.Credential["username"].(string) + require.True(t, ok) + assert.Equal(t, c.TargetSshUser, retrievedUser) + + retrievedKey, ok := v.Credential["private_key"].(string) + require.True(t, ok) + k, err := os.ReadFile(c.TargetSshKeyPath) + require.NoError(t, err) + keysMatch := string(k) == retrievedKey // This is done to prevent printing out key info + require.True(t, keysMatch, "Key retrieved from vault does not match expected value") + t.Log("Successfully retrieved credentials for target") + } else if v.CredentialSource.CredentialType == "username_password" { + retrievedUser := fmt.Sprintf("%s", v.Credential["username"]) + retrievedPassword := fmt.Sprintf("%s", v.Credential["password"]) + assert.Equal(t, c.TargetSshUser, retrievedUser) + assert.Equal(t, password, retrievedPassword) + t.Log("Successfully retrieved password credentials for target") + } + } } diff --git a/testing/internal/e2e/vault/boundary-controller-policy.hcl b/testing/internal/e2e/vault/testdata/boundary-controller-policy.hcl similarity index 100% rename from testing/internal/e2e/vault/boundary-controller-policy.hcl rename to testing/internal/e2e/vault/testdata/boundary-controller-policy.hcl diff --git a/testing/internal/e2e/vault/vault.go b/testing/internal/e2e/vault/vault.go index cb0a3b85c1..523007e53e 100644 --- a/testing/internal/e2e/vault/vault.go +++ b/testing/internal/e2e/vault/vault.go @@ -3,17 +3,20 @@ package vault import ( "context" + "embed" "fmt" "os" - "path" - "runtime" "testing" "github.com/hashicorp/boundary/testing/internal/e2e" + "github.com/hashicorp/go-secure-stdlib/base62" "github.com/kelseyhightower/envconfig" "github.com/stretchr/testify/require" ) +//go:embed testdata/boundary-controller-policy.hcl +var boundaryPolicyFile embed.FS + type config struct { VaultAddr string `envconfig:"VAULT_ADDR" required:"true"` // e.g. "http://127.0.0.1:8200" VaultToken string `envconfig:"VAULT_TOKEN" required:"true"` @@ -31,71 +34,108 @@ func loadConfig() (*config, error) { // Setup verifies if appropriate credentials are set and adds the boundary controller // policy to vault. Returns the vault address. -func Setup(t testing.TB) (string, string) { +func Setup(t testing.TB) (vaultAddr string, boundaryPolicyName string, kvPolicyFilePath string) { c, err := loadConfig() require.NoError(t, err) + vaultAddr = c.VaultAddr - _, filename, _, ok := runtime.Caller(0) - require.True(t, ok) - ctx := context.Background() - policyName := "boundary-controller" - 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", - e2e.WithArgs("policy", "delete", policyName), - ) - require.NoError(t, output.Err, string(output.Stderr)) - }) + // Set up boundary policy + data, err := boundaryPolicyFile.ReadFile("testdata/boundary-controller-policy.hcl") + require.NoError(t, err) + boundaryPolicyFilePath := fmt.Sprintf("%s/%s", t.TempDir(), "boundary-controller-policy.hcl") + f, err := os.Create(boundaryPolicyFilePath) + require.NoError(t, err) + _, err = f.WriteString(string(data)) + require.NoError(t, err) - return c.VaultAddr, policyName + boundaryPolicyName = WritePolicy(t, context.Background(), boundaryPolicyFilePath) + + // Create kv policy + kvPolicyFilePath = fmt.Sprintf("%s/%s", t.TempDir(), "kv-policy.hcl") + _, err = os.Create(kvPolicyFilePath) + require.NoError(t, err) + + return } // CreateKvPrivateKeyCredential creates a private key credential in vault and creates a vault policy // to be able to read that credential. Returns the name of the policy. -func CreateKvPrivateKeyCredential(t testing.TB, secretName string, secretPath string, user string, keyPath string) string { - // Create policy file to read secret - kvPolicyFileName := "kv-policy-test.hcl" - kvPolicyFilePath := fmt.Sprintf("%s/%s", t.TempDir(), kvPolicyFileName) +func CreateKvPrivateKeyCredential(t testing.TB, secretPath string, user string, keyPath string, kvPolicyFilePath string) string { + secretName, err := base62.Random(16) + require.NoError(t, err) - f, err := os.Create(kvPolicyFilePath) + // Update policy file + f, err := os.OpenFile(kvPolicyFilePath, os.O_APPEND|os.O_WRONLY, 0o644) require.NoError(t, err) - _, err = f.WriteString(fmt.Sprintf("path \"%s/data/%s\" { capabilities = [\"read\"] }", + _, err = f.WriteString(fmt.Sprintf("path \"%s/data/%s\" { capabilities = [\"read\"] }\n", secretPath, secretName, )) require.NoError(t, err) - // Add policy to vault - ctx := context.Background() - policyName := "kv-read" - output := e2e.RunCommand(ctx, "vault", - e2e.WithArgs("policy", "write", policyName, kvPolicyFilePath), + // Create secret + output := e2e.RunCommand(context.Background(), "vault", + e2e.WithArgs( + "kv", "put", + "-mount", secretPath, + secretName, + "username="+user, + "private_key=@"+keyPath, + ), ) require.NoError(t, output.Err, string(output.Stderr)) - t.Cleanup(func() { - output := e2e.RunCommand(ctx, "vault", - e2e.WithArgs("policy", "delete", policyName), - ) - require.NoError(t, output.Err, string(output.Stderr)) - }) + + return secretName +} + +// CreateKvPasswordCredential creates a username/password credential in vault and creates a vault +// policy to be able to read that credential. Returns the name of the policy +func CreateKvPasswordCredential(t testing.TB, secretPath string, user string, kvPolicyFilePath string) (secretName string, password string) { + secretName, err := base62.Random(16) + require.NoError(t, err) + + // Update policy file + f, err := os.OpenFile(kvPolicyFilePath, os.O_APPEND|os.O_WRONLY, 0o644) + require.NoError(t, err) + _, err = f.WriteString(fmt.Sprintf("path \"%s/data/%s\" { capabilities = [\"read\"] }\n", + secretPath, + secretName, + )) + require.NoError(t, err) // Create secret - output = e2e.RunCommand(ctx, "vault", + password, err = base62.Random(16) + require.NoError(t, err) + output := e2e.RunCommand(context.Background(), "vault", e2e.WithArgs( "kv", "put", "-mount", secretPath, secretName, "username="+user, - "private_key=@"+keyPath, + "password="+password, ), ) require.NoError(t, output.Err, string(output.Stderr)) + return +} + +// WritePolicy adds a policy to vault. Provide a name for the policy that you want to create as well +// as the path to the file that contains the policy definition. Returns a policy name +func WritePolicy(t testing.TB, ctx context.Context, policyFilePath string) string { + policyName, err := base62.Random(16) + require.NoError(t, err) + + output := e2e.RunCommand(ctx, "vault", + e2e.WithArgs("policy", "write", policyName, policyFilePath), + ) + require.NoError(t, output.Err, string(output.Stderr)) + t.Cleanup(func() { + output := e2e.RunCommand(ctx, "vault", + e2e.WithArgs("policy", "delete", policyName), + ) + require.NoError(t, output.Err, string(output.Stderr)) + }) + return policyName }