diff --git a/ui/admin/tests/e2e/helpers/boundary-cli.js b/ui/admin/tests/e2e/helpers/boundary-cli.js index 8d7005d8d..5e81ed8c7 100644 --- a/ui/admin/tests/e2e/helpers/boundary-cli.js +++ b/ui/admin/tests/e2e/helpers/boundary-cli.js @@ -77,3 +77,34 @@ exports.deleteOrg = async (orgId) => { console.log(`${e.stderr}`); } }; + +/** + * Uses the boundary CLI to get a session created for the specified target + * @param {string} orgName Name of the organization with the specified project + * @param {string} projectName Name of project with the specified target + * @param {string} targetName Name of the target that the anticipated session is created for + * @returns An object representing an active session created for the specified target + */ +exports.getSessionCli = async (orgName, projectName, targetName) => { + let session; + try { + const orgs = JSON.parse(execSync('boundary scopes list -format json')); + const org = orgs.items.filter((obj) => obj.name == orgName)[0]; + const projects = JSON.parse( + execSync(`boundary scopes list -format json -scope-id ${org.id}`) + ); + const project = projects.items.filter((obj) => obj.name == projectName)[0]; + const targets = JSON.parse( + execSync(`boundary targets list -format json -scope-id ${project.id}`) + ); + const target = targets.items.filter((obj) => obj.name == targetName)[0]; + session = JSON.parse( + execSync( + `boundary targets authorize-session -id ${target.id} -format json` + ) + ); + } catch (e) { + console.log(`${e.stderr}`); + } + return session; +}; diff --git a/ui/admin/tests/e2e/helpers/boundary-ui.js b/ui/admin/tests/e2e/helpers/boundary-ui.js index 14dbc37ab..5a2ea9ba2 100644 --- a/ui/admin/tests/e2e/helpers/boundary-ui.js +++ b/ui/admin/tests/e2e/helpers/boundary-ui.js @@ -249,3 +249,37 @@ exports.waitForSessionToBeVisible = async (page, targetName) => { throw new Error('Session is not visible'); } }; + +/** + * Uses the UI to navigate to the specified Target and add the Brokered Credentials to it. + * @param {Page} page Playwright page object + * @param {string} targetName Name of the target associated with the session + * @param {string} credentialName Name of the credentials to be added to the target + */ +exports.addBrokeredCredentialsToTarget = async (page, targetName, credentialName) => { + await page + .getByRole('navigation', { name: 'Resources' }) + .getByRole('link', { name: 'Targets' }) + .click(); + await page.getByRole('link', { name: targetName }).click(); + await page + .getByRole('link', { name: 'Brokered Credentials', exact: true }) + .click(); + await page + .getByRole('article') + .getByRole('link', { name: 'Add Brokered Credentials', exact: true }) + .click(); + await page + .getByRole('cell', { name: credentialName }) + .locator('..') + .getByRole('checkbox') + .click({ force: true }); + await page + .getByRole('button', { name: 'Add Brokered Credentials', exact: true }) + .click(); + await expect( + page.getByRole('alert').getByText('Success', { exact: true }) + ).toBeVisible(); + await page.getByRole('button', { name: 'Dismiss' }).click(); + await expect(page.getByRole('link', { name: credentialName })).toBeVisible(); +} diff --git a/ui/admin/tests/e2e/tests/credential-store-static.spec.js b/ui/admin/tests/e2e/tests/credential-store-static.spec.js index a7d3bf72a..3f6591f67 100644 --- a/ui/admin/tests/e2e/tests/credential-store-static.spec.js +++ b/ui/admin/tests/e2e/tests/credential-store-static.spec.js @@ -5,13 +5,13 @@ /* eslint-disable no-undef */ const { test, expect } = require('@playwright/test'); -const { execSync } = require('child_process'); const { readFile } = require('fs/promises'); const { nanoid } = require('nanoid'); const { checkEnv, authenticatedState } = require('../helpers/general'); const { authenticateBoundaryCli, checkBoundaryCli, + getSessionCli, } = require('../helpers/boundary-cli'); const { createNewOrg, @@ -20,6 +20,7 @@ const { createNewHostSet, createNewHostInHostSet, createNewTarget, + addBrokeredCredentialsToTarget, addHostSourceToTarget, } = require('../helpers/boundary-ui'); @@ -36,17 +37,19 @@ test.beforeAll(async () => { await checkBoundaryCli(); }); +let orgName; +let projectName; +let targetName; + test.beforeEach(async ({ page }) => { await page.goto('/'); -}); -test('Static Credential Store (User & Key Pair)', async ({ page }) => { - const orgName = await createNewOrg(page); - const projectName = await createNewProject(page); + orgName = await createNewOrg(page); + projectName = await createNewProject(page); await createNewHostCatalog(page); const hostSetName = await createNewHostSet(page); await createNewHostInHostSet(page); - const targetName = await createNewTarget(page); + targetName = await createNewTarget(page); await addHostSourceToTarget(page, hostSetName); const credentialStoreName = 'Credential Store ' + nanoid(); @@ -66,7 +69,9 @@ test('Static Credential Store (User & Key Pair)', async ({ page }) => { await expect( page.getByRole('link', { name: credentialStoreName }) ).toBeVisible(); +}); +test('Static Credential Store (User & Key Pair)', async ({ page }) => { const credentialName = 'Credential ' + nanoid(); await page.getByRole('link', { name: 'Credentials', exact: true }).click(); await page.getByRole('link', { name: 'New', exact: true }).click(); @@ -90,47 +95,10 @@ test('Static Credential Store (User & Key Pair)', async ({ page }) => { await page.getByRole('button', { name: 'Dismiss' }).click(); await expect(page.getByRole('link', { name: credentialName })).toBeVisible(); - await page - .getByRole('navigation', { name: 'Resources' }) - .getByRole('link', { name: 'Targets' }) - .click(); - await page.getByRole('link', { name: targetName }).click(); - await page - .getByRole('link', { name: 'Brokered Credentials', exact: true }) - .click(); - await page - .getByRole('article') - .getByRole('link', { name: 'Add Brokered Credentials', exact: true }) - .click(); - await page - .getByRole('cell', { name: credentialName }) - .locator('..') - .getByRole('checkbox') - .click({ force: true }); - await page - .getByRole('button', { name: 'Add Brokered Credentials', exact: true }) - .click(); - await expect( - page.getByRole('alert').getByText('Success', { exact: true }) - ).toBeVisible(); - await page.getByRole('button', { name: 'Dismiss' }).click(); - await expect(page.getByRole('link', { name: credentialName })).toBeVisible(); + await addBrokeredCredentialsToTarget(page, targetName, credentialName); await authenticateBoundaryCli(); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - const projects = JSON.parse( - execSync(`boundary scopes list -format json -scope-id ${org.id}`) - ); - const project = projects.items.filter((obj) => obj.name == projectName)[0]; - const targets = JSON.parse( - execSync(`boundary targets list -format json -scope-id ${project.id}`) - ); - const target = targets.items.filter((obj) => obj.name == targetName)[0]; - - const session = JSON.parse( - execSync(`boundary targets authorize-session -id ${target.id} -format json`) - ); + const session = await getSessionCli(orgName, projectName, targetName); const retrievedUser = session.item.credentials[0].credential.username; const retrievedKey = session.item.credentials[0].credential.private_key; @@ -146,3 +114,107 @@ test('Static Credential Store (User & Key Pair)', async ({ page }) => { throw new Error('Stored Key does not match'); } }); + +test('Static Credential Store (Username & Password)', async ({ page }) => { + const credentialName = 'Credential ' + nanoid(); + await page.getByRole('link', { name: 'Credentials', exact: true }).click(); + await page.getByRole('link', { name: 'New', exact: true }).click(); + await page.getByLabel('Name', { exact: true }).fill(credentialName); + await page.getByLabel('Description').fill('This is an automated test'); + await page + .getByRole('group', { name: 'Type' }) + .getByLabel('Username & Password') + .click(); + await page + .getByLabel('Username', { exact: true }) + .fill(process.env.E2E_SSH_USER); + const testPassword = 'password'; + await page.getByLabel('Password', { exact: true }).fill(testPassword); + await page.getByRole('button', { name: 'Save' }).click(); + await expect( + page.getByRole('alert').getByText('Success', { exact: true }) + ).toBeVisible(); + await page.getByRole('button', { name: 'Dismiss' }).click(); + await expect(page.getByRole('link', { name: credentialName })).toBeVisible(); + + await addBrokeredCredentialsToTarget(page, targetName, credentialName); + + await authenticateBoundaryCli(); + const session = await getSessionCli(orgName, projectName, targetName); + const retrievedUser = session.item.credentials[0].credential.username; + const retrievedPassword = session.item.credentials[0].credential.password; + + if (process.env.E2E_SSH_USER != retrievedUser) { + throw new Error( + 'Stored User does not match. EXPECTED: ' + + process.env.E2E_SSH_USER + + ', ACTUAL: ' + + retrievedUser + ); + } + if (testPassword != retrievedPassword) { + throw new Error( + 'Stored Password does not match. EXPECTED: ' + + testPassword + + ', ACTUAL: ' + + retrievedPassword + ); + } +}); + +test('Static Credential Store (JSON)', async ({ page }) => { + const credentialName = 'Credential ' + nanoid(); + await page.getByRole('link', { name: 'Credentials', exact: true }).click(); + await page.getByRole('link', { name: 'New', exact: true }).click(); + await page.getByLabel('Name', { exact: true }).fill(credentialName); + await page.getByLabel('Description').fill('This is an automated test'); + await page.getByRole('group', { name: 'Type' }).getByLabel('JSON').click(); + await page.getByText('{}').click(); + const testName = 'name-json'; + const testPassword = 'password-json'; + const testId = 'id-json'; + await page.keyboard.type( + `"username": "${testName}", + "password": "${testPassword}", + "id": "${testId}"` + ); + await page.getByRole('button', { name: 'Save' }).click(); + await expect( + page.getByRole('alert').getByText('Success', { exact: true }) + ).toBeVisible(); + await page.getByRole('button', { name: 'Dismiss' }).click(); + await expect(page.getByRole('link', { name: credentialName })).toBeVisible(); + + await addBrokeredCredentialsToTarget(page, targetName, credentialName); + + await authenticateBoundaryCli(); + const session = await getSessionCli(orgName, projectName, targetName); + const retrievedUser = session.item.credentials[0].credential.username; + const retrievedPassword = session.item.credentials[0].credential.password; + const retrievedId = session.item.credentials[0].credential.id; + + if (testName != retrievedUser) { + throw new Error( + 'Stored User does not match. EXPECTED: ' + + process.env.E2E_SSH_USER + + ', ACTUAL: ' + + retrievedUser + ); + } + if (testPassword != retrievedPassword) { + throw new Error( + 'Stored Password does not match. EXPECTED: ' + + testPassword + + ', ACTUAL: ' + + retrievedPassword + ); + } + if (testId != retrievedId) { + throw new Error( + 'Stored ID does not match. EXPECTED: ' + + testId + + ', ACTUAL: ' + + retrievedId + ); + } +});