diff --git a/ui/admin/tests/e2e/pages/credential-stores.mjs b/ui/admin/tests/e2e/pages/credential-stores.mjs index 6a12782fc..c16e2cf70 100644 --- a/ui/admin/tests/e2e/pages/credential-stores.mjs +++ b/ui/admin/tests/e2e/pages/credential-stores.mjs @@ -187,10 +187,11 @@ export class CredentialStoresPage extends BaseResourcePage { * Creates a vault-generic credential library. Assumes you have selected * the desired credential store. * @param {string} vaultPath path to secret in vault - * @param {string} credentialType type of credential for credential injection + * @param {string} credentialType type of credential for credential injection. + * Can be set to null if injection is not used * @returns Name of the credential library */ - async createVaultGenericCredentialLibrary(vaultPath, credentialType) { + async createVaultGenericCredentialLibraryEnt(vaultPath, credentialType) { const credentialLibraryName = 'Credential Library ' + nanoid(); await this.page.getByRole('link', { name: 'Credential Libraries' }).click(); await this.page.getByRole('link', { name: 'New', exact: true }).click(); @@ -205,9 +206,12 @@ export class CredentialStoresPage extends BaseResourcePage { .getByLabel('Generic Secrets') .click(); await this.page.getByLabel('Vault Path').fill(vaultPath); - await this.page - .getByRole('combobox', { name: 'Credential Type' }) - .selectOption(credentialType); + + if (credentialType) { + await this.page + .getByRole('combobox', { name: 'Credential Type' }) + .selectOption(credentialType); + } await this.page.getByRole('button', { name: 'Save' }).click(); await this.dismissSuccessAlert(); @@ -222,7 +226,7 @@ export class CredentialStoresPage extends BaseResourcePage { * @param {string} username username for the credential * @returns Name of the credential library */ - async createVaultSshCertificateCredentialLibrary(vaultPath, username) { + async createVaultSshCertificateCredentialLibraryEnt(vaultPath, username) { const credentialLibraryName = 'Credential Library ' + nanoid(); await this.page.getByRole('link', { name: 'Credential Libraries' }).click(); diff --git a/ui/admin/tests/e2e/tests/credential-store-vault-ent.spec.mjs b/ui/admin/tests/e2e/tests/credential-store-vault-ent.spec.mjs new file mode 100644 index 000000000..d670ba908 --- /dev/null +++ b/ui/admin/tests/e2e/tests/credential-store-vault-ent.spec.mjs @@ -0,0 +1,120 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { test } from '../playwright.config.mjs' +import { expect } from '@playwright/test'; +import { execSync } from 'child_process'; +import { nanoid } from 'nanoid'; +import { readFile } from 'fs/promises'; + +import { authenticatedState } from '../global-setup.mjs'; +import { + authenticateBoundaryCli, + authorizeSessionByTargetIdCli, + checkBoundaryCli, + deleteScopeCli, + getOrgIdFromNameCli, + getProjectIdFromNameCli, + getTargetIdFromNameCli, +} from '../helpers/boundary-cli.mjs'; +import { checkVaultCli } from '../helpers/vault-cli.mjs'; +import { CredentialStoresPage } from '../pages/credential-stores.mjs'; +import { OrgsPage } from '../pages/orgs.mjs'; +import { ProjectsPage } from '../pages/projects.mjs'; +import { TargetsPage } from '../pages/targets.mjs'; + +const secretsPath = 'e2e_secrets'; +const secretName = 'cred'; +const secretPolicyName = 'kv-policy'; +const boundaryPolicyName = 'boundary-controller'; + +test.use({ storageState: authenticatedState }); + +test.beforeAll(async () => { + await checkBoundaryCli(); + await checkVaultCli(); +}); + +test.beforeEach(async ({ page }) => { + execSync(`vault policy delete ${secretPolicyName}`); + execSync(`vault policy delete ${boundaryPolicyName}`); + execSync(`vault secrets disable ${secretsPath}`); + + await page.goto('/'); +}); + +test('Vault Credential Store (User & Key Pair) @ent @aws @docker', async ({ + page, + baseURL, + adminAuthMethodId, + adminLoginName, + adminPassword, + sshUser, + sshKeyPath, + targetAddress, + targetPort, + vaultAddr, +}) => { + let orgId; + try { + execSync( + `vault policy write ${boundaryPolicyName} ./tests/e2e/tests/fixtures/boundary-controller-policy.hcl`, + ); + execSync(`vault secrets enable -path=${secretsPath} kv-v2`); + execSync( + `vault kv put -mount ${secretsPath} ${secretName} ` + + ` username=${sshUser}` + + ` private_key=@${sshKeyPath}`, + ); + execSync( + `vault policy write ${secretPolicyName} ./tests/e2e/tests/fixtures/kv-policy.hcl`, + ); + const vaultToken = JSON.parse( + execSync( + `vault token create` + + ` -no-default-policy=true` + + ` -policy=${boundaryPolicyName}` + + ` -policy=${secretPolicyName}` + + ` -orphan=true` + + ` -period=20m` + + ` -renewable=true` + + ` -format=json`, + ), + ); + const clientToken = vaultToken.auth.client_token; + + const orgsPage = new OrgsPage(page); + const orgName = await orgsPage.createOrg(); + const projectsPage = new ProjectsPage(page); + const projectName = await projectsPage.createProject(); + const targetsPage = new TargetsPage(page); + const targetName = await targetsPage.createSshTargetWithAddressEnt(targetAddress, targetPort); + const credentialStoresPage = new CredentialStoresPage(page); + await credentialStoresPage.createVaultCredentialStore(vaultAddr, clientToken); + const credentialLibraryName = await credentialStoresPage.createVaultGenericCredentialLibraryEnt( + `${secretsPath}/data/${secretName}`, + 'SSH Private Key', + ) + await targetsPage.addInjectedCredentialsToTarget( + targetName, + credentialLibraryName, + ); + + await authenticateBoundaryCli( + baseURL, + adminAuthMethodId, + adminLoginName, + adminPassword, + ); + orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); + await authorizeSessionByTargetIdCli(targetId); + } finally { + if (orgId) { + await deleteScopeCli(orgId); + } + } +}); diff --git a/ui/admin/tests/e2e/tests/ssh-certificate-injection-vault-ent.spec.mjs b/ui/admin/tests/e2e/tests/ssh-certificate-injection-vault-ent.spec.mjs index e5f8a22be..64661c66b 100644 --- a/ui/admin/tests/e2e/tests/ssh-certificate-injection-vault-ent.spec.mjs +++ b/ui/admin/tests/e2e/tests/ssh-certificate-injection-vault-ent.spec.mjs @@ -112,7 +112,7 @@ test('SSH Certificate Injection @ent @docker', async ({ const credentialStoresPage = new CredentialStoresPage(page); await credentialStoresPage.createVaultCredentialStore(vaultAddr, clientToken); const credentialLibraryName = - await credentialStoresPage.createVaultSshCertificateCredentialLibrary( + await credentialStoresPage.createVaultSshCertificateCredentialLibraryEnt( `${secretsPath}/issue/${secretName}`, sshUser, ); diff --git a/ui/admin/tests/e2e/tests/ssh-credential-injection-vault-ent.spec.mjs b/ui/admin/tests/e2e/tests/ssh-credential-injection-vault-ent.spec.mjs index f63e6725c..b597fe836 100644 --- a/ui/admin/tests/e2e/tests/ssh-credential-injection-vault-ent.spec.mjs +++ b/ui/admin/tests/e2e/tests/ssh-credential-injection-vault-ent.spec.mjs @@ -102,7 +102,7 @@ test('SSH Credential Injection (Vault User & Key Pair) @ent @docker', async ({ const credentialStoresPage = new CredentialStoresPage(page); await credentialStoresPage.createVaultCredentialStore(vaultAddr, clientToken); const credentialLibraryName = - await credentialStoresPage.createVaultGenericCredentialLibrary( + await credentialStoresPage.createVaultGenericCredentialLibraryEnt( `${secretsPath}/data/${secretName}`, 'SSH Private Key', );