diff --git a/ui/admin/package.json b/ui/admin/package.json index a71dcf878..ff74a1674 100644 --- a/ui/admin/package.json +++ b/ui/admin/package.json @@ -33,7 +33,7 @@ "pretest": "yarn clean:coverage", "test": "concurrently \"npm:test:*\" --names \"test:\"", "test:ember": "COVERAGE=true ember exam --test-port 0 --split=4 --parallel=1 --random", - "e2e": "yarn playwright test --config ./tests/e2e/playwright.config.js", + "e2e": "yarn playwright test --config ./tests/e2e/playwright.config.mjs", "e2e:ce:aws": "yarn run e2e --grep \"(?=.*@ce)(?=.*@aws)\"", "e2e:ce:docker": "yarn run e2e --grep \"(?=.*@ce)(?=.*@docker)\"", "e2e:ent:aws": "yarn run e2e --grep \"(?=.*@ent)(?=.*@aws)\"", diff --git a/ui/admin/tests/e2e/global-setup.js b/ui/admin/tests/e2e/global-setup.mjs similarity index 82% rename from ui/admin/tests/e2e/global-setup.js rename to ui/admin/tests/e2e/global-setup.mjs index 910ea031e..e17b5806b 100644 --- a/ui/admin/tests/e2e/global-setup.js +++ b/ui/admin/tests/e2e/global-setup.mjs @@ -3,10 +3,10 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { chromium } = require('@playwright/test'); -const { checkEnv, authenticatedState } = require('./helpers/general'); +import { chromium } from '@playwright/test'; +import { checkEnv } from './helpers/general.mjs'; -module.exports = async () => { +async function globalSetup() { await checkEnv([ 'BOUNDARY_ADDR', 'E2E_PASSWORD_ADMIN_LOGIN_NAME', @@ -37,4 +37,9 @@ module.exports = async () => { process.env.E2E_TOKEN = state.authenticated.token; await browser.close(); -}; +} + +export default globalSetup; + +export const authenticatedState = + './tests/e2e/artifacts/authenticated-state.json'; diff --git a/ui/admin/tests/e2e/helpers/boundary-cli.js b/ui/admin/tests/e2e/helpers/boundary-cli.js deleted file mode 100644 index 7229b5d27..000000000 --- a/ui/admin/tests/e2e/helpers/boundary-cli.js +++ /dev/null @@ -1,671 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -const { execSync, exec } = require('child_process'); -const { nanoid } = require('nanoid'); - -/** - * Checks that the boundary cli is available - */ -exports.checkBoundaryCli = async () => { - try { - execSync('which boundary'); - } catch (e) { - throw new Error('boundary does not exist on the path'); - } -}; - -/** - * Uses the boundary CLI to authenticate to the specified Boundary instance - * @param {string} addr Address of the Boundary instance to be authenticated to - * @param {string} authMethodId ID of the auth method to be used for authentication - * @param {string} loginName Login name to be used for authentication - * @param {string} password Password to be used for authentication - */ -exports.authenticateBoundaryCli = async ( - addr, - authMethodId, - loginName, - password, -) => { - try { - execSync( - 'boundary authenticate password' + - ` -addr=${addr}` + - ` -auth-method-id=${authMethodId}` + - ` -login-name=${loginName}` + - ' -password=env://BPASS', - { env: { ...process.env, BPASS: password } }, - ); - } catch (e) { - console.log(`${e.stderr}`); - } -}; - -/** - * Uses the boundary CLI to connect to the specified target - * exec is used here to keep the session open - * @param {string} targetId ID of the target to be connected to - * @param {string} sshUser User to be used for the ssh connection - * @param {string} sshKeyPath Path to the ssh key to be used for the ssh connection - * @returns ChildProcess representing the result of the command execution - */ -exports.connectToTarget = async (targetId, sshUser, sshKeyPath) => { - let connect; - try { - connect = exec( - `boundary connect -target-id=${targetId}` + - ' -exec /usr/bin/ssh --' + - ` -l ${sshUser}` + - ` -i ${sshKeyPath}` + - ' -o UserKnownHostsFile=/dev/null' + - ' -o StrictHostKeyChecking=no' + - ' -o IdentitiesOnly=yes' + // forces the use of the provided key - ' -p {{boundary.port}}' + - ' {{boundary.ip}}', - ); - } catch (e) { - console.log(`${e.stderr}`); - } - return connect; -}; - -/** - * Uses the boundary CLI to connect ssh to the specified target - * exec is used here to keep the session open - * @param {string} targetId ID of the target to be connected to - * @returns ChildProcess representing the result of the command execution - */ -exports.connectSshToTarget = async (targetId) => { - let connect; - try { - connect = exec( - 'boundary connect ssh' + - ` -target-id=${targetId}` + - ' --' + - ' -o UserKnownHostsFile=/dev/null' + - ' -o StrictHostKeyChecking=no' + - ' -o IdentitiesOnly=yes', // forces the use of the provided key - ); - } catch (e) { - console.log(`${e.stderr}`); - } - return connect; -}; - -/** - * Uses the bounadry CLI to connect to the specified alias - * If the alias - * @param {string} alias alias of the target to be connected to - * @returns ChildProcess representing the result of the command execution - */ -exports.authorizeAlias = async (alias) => { - try { - execSync(`boundary targets authorize-session ${alias}`); - } catch (e) { - throw new Error(`Failed to connect to alias: ${e.stderr}`); - } -}; - -/** - * Uses the boundary CLI to create a new org. - * @returns {Promise} new org's id - */ -exports.createOrgCli = async () => { - const orgName = 'Org ' + nanoid(); - let newOrg; - try { - newOrg = JSON.parse( - execSync( - `boundary scopes create \ - -name="${orgName}" \ - -scope-id=global \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return newOrg.id; -}; - -/** - * Uses the boundary CLI to delete the specified organization - * @param {string} orgId ID of the organization to be deleted - */ -exports.deleteOrgCli = async (orgId) => { - try { - execSync('boundary scopes delete -id=' + orgId); - } catch (e) { - console.log(`${e.stderr}`); - } -}; - -/** - * Uses the boundary CLI to delete the specified storage bucket - * @param {string} storageBucketId ID of the storage bucket to be deleted - */ -exports.deleteStorageBucketCli = async (storageBucketId) => { - try { - execSync('boundary storage-buckets delete -id=' + storageBucketId); - } catch (e) { - console.log(`${e.stderr}`); - } -}; - -/** - * Uses the boundary CLI to delete the specified policy - * @param {string} policyId ID of the policy to be deleted - */ -exports.deletePolicyCli = async (policyId) => { - try { - execSync('boundary policies delete -id=' + policyId); - } catch (e) { - console.log(`${e.stderr}`); - } -}; - -/** - * Uses the boundary CLI to delete the specified alias - * @param {string} aliasValue Value of the alias to be deleted - */ -exports.deleteAliasCli = async (aliasValue) => { - try { - const aliases = JSON.parse(execSync('boundary aliases list -format json')); - const alias = aliases.items.filter((obj) => obj.value == aliasValue)[0]; - - execSync('boundary aliases delete -id=' + alias.id); - } catch (e) { - console.log(`${e.stderr}`); - } -}; - -/** - * Uses the boundary CLI to create a new project. - * @param {string} orgId ID of the organization under which the project will be created. - * @returns {Promise} new project's ID - */ -exports.createProjectCli = async (orgId) => { - const projectName = 'Project ' + nanoid(); - let newProject; - try { - newProject = JSON.parse( - execSync( - `boundary scopes create \ - -name="${projectName}" \ - -scope-id=${orgId} \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return newProject.id; -}; - -/** - * Uses the boundary CLI to create a new controller-led worker. - * @returns {Promise} new worker's ID - */ -exports.createControllerLedWorkerCli = async () => { - const workerName = 'worker-' + nanoid(); - let newWorker; - try { - newWorker = JSON.parse( - execSync( - `boundary workers create controller-led \ - -name="${workerName.toLowerCase()}" \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return newWorker.id; -}; - -/** - * Uses the boundary CLI to create a new password auth-method. - * @param {string} scopeId ID of the scope under which the auth-method will be created. - * @returns {Promise} new auth-method's ID - */ -exports.createPasswordAuthMethodCli = async (scopeId) => { - const authMethodName = 'auth-method-' + nanoid(); - let newAuthMethod; - try { - newAuthMethod = JSON.parse( - execSync( - `boundary auth-methods create password \ - -name "${authMethodName}" \ - -scope-id ${scopeId} \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return newAuthMethod.id; -}; - -/** - * Uses the boundary CLI to make an auth-method primary. - * @param {string} scopeId ID of the scope that the auth-method belongs to. - * @param {string} authMethodId ID of the auth method that will be made primary. - */ -exports.makeAuthMethodPrimaryCli = async (scopeId, authMethodId) => { - try { - execSync( - `boundary scopes update \ - -id=${scopeId} \ - -primary-auth-method-id ${authMethodId} \ - -format json`, - ); - } catch (e) { - console.log(`${e.stderr}`); - } -}; - -/** - * Uses the boundary CLI to create a new password account. - * @param {string} authMethodId ID of the auth-method that the new account will be created for. - * @returns {Promise} new account's ID - */ -exports.createPasswordAccountCli = async (authMethodId) => { - let passwordAccount; - const login = 'test-login'; - try { - passwordAccount = JSON.parse( - execSync( - `boundary accounts create password \ - -auth-method-id ${authMethodId} \ - -login-name ${login} \ - -password env://ACCOUNT_PASSWORD \ - -format json`, - { env: { ...process.env, ACCOUNT_PASSWORD: 'test-password' } }, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return passwordAccount.id; -}; - -/** - * Uses the boundary CLI to create a new role. - * @param {string} scopeId ID of the scope under which the role will be created. - * @returns {Promise} new role's ID - */ -exports.createRoleCli = async (scopeId) => { - const roleName = 'role-' + nanoid(); - let role; - try { - role = JSON.parse( - execSync( - `boundary roles create \ - -scope-id ${scopeId} \ - -name ${roleName} \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return role.id; -}; - -/** - * Uses the boundary CLI to create a new group. - * @param {string} scopeId ID of the scope under which the group will be created. - * @returns {Promise} new group's ID - */ -exports.createGroupCli = async (scopeId) => { - const groupName = 'group-' + nanoid(); - let group; - try { - group = JSON.parse( - execSync( - `boundary groups create \ - -scope-id ${scopeId} \ - -name ${groupName} \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return group.id; -}; - -/** - * Uses the boundary CLI to create a new user. - * @param {string} scopeId ID of the scope under which the user will be created. - * @returns {Promise} new user's ID - */ -exports.createUserCli = async (scopeId) => { - const userName = 'user-' + nanoid(); - let user; - try { - user = JSON.parse( - execSync( - `boundary users create \ - -scope-id ${scopeId} \ - -name ${userName} \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return user.id; -}; - -/** - * Uses the boundary CLI to create a new static host catalog. - * @param {string} projectId ID of the project under which the host catalog will be created. - * @returns {Promise} new host catalog's ID - */ -exports.createStaticHostCatalogCli = async (projectId) => { - const hostCatalogName = 'static-host-catalog-' + nanoid(); - let hostCatalog; - try { - hostCatalog = JSON.parse( - execSync( - `boundary host-catalogs create static \ - -scope-id ${projectId} \ - -name ${hostCatalogName} \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return hostCatalog.id; -}; - -/** - * Uses the boundary CLI to create a new dynamic AWS host catalog. - * @param {string} projectId ID of the project under which the host catalog will be created. - * @param {string} region Name of the AWS region that the host catalog will be created for. - * @returns {Promise} new host catalog's ID - */ -exports.createDynamicAwsHostCatalogCli = async (projectId, region) => { - const hostCatalogName = 'dynamic-aws-host-catalog-' + nanoid(); - let hostCatalog; - try { - hostCatalog = JSON.parse( - execSync( - `boundary host-catalogs create plugin \ - -name ${hostCatalogName} \ - -scope-id ${projectId} \ - -plugin-name aws \ - -attr disable_credential_rotation=true \ - -attr region=${region} \ - -secret access_key_id=env://E2E_AWS_ACCESS_KEY_ID \ - -secret secret_access_key=env://E2E_AWS_SECRET_ACCESS_KEY \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return hostCatalog.id; -}; - -/** - * Uses the boundary CLI to create a new static host. - * @param {string} hostCatalogId ID of the host catalog that the host will be created for. - * @returns {Promise} new host's ID - */ -exports.createStaticHostCli = async (hostCatalogId) => { - const hostName = 'static-host-' + nanoid(); - let host; - try { - host = JSON.parse( - execSync( - `boundary hosts create static \ - -host-catalog-id ${hostCatalogId} \ - -name ${hostName} \ - -address localhost \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return host.id; -}; - -/** - * Uses the boundary CLI to create a new static host set. - * @param {string} hostCatalogId ID of the host catalog that the host set will be created for. - * @returns {Promise} new host set's ID - */ -exports.createHostSetCli = async (hostCatalogId) => { - const hostSetName = 'static-host-' + nanoid(); - let hostSet; - try { - hostSet = JSON.parse( - execSync( - `boundary host-sets create static \ - -host-catalog-id ${hostCatalogId} \ - -name ${hostSetName} \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return hostSet.id; -}; - -/** - * Uses the boundary CLI to create a new static credential store. - * @param {string} projectId ID of the project under which the credential store will be created. - * @returns {Promise} new credential store's ID - */ -exports.createStaticCredentialStoreCli = async (projectId) => { - const credentialStoreName = 'static-credential-store-' + nanoid(); - let staticCredentialStore; - try { - staticCredentialStore = JSON.parse( - execSync( - `boundary credential-stores create static \ - -scope-id ${projectId} \ - -name ${credentialStoreName} \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return staticCredentialStore.id; -}; - -/** - * Uses the boundary CLI to create a new vault credential store. - * @param {string} projectId ID of the project under which the credential store will be created. - * @param {string} vaultAddr Address of the vault that the credential store will be created for. - * @param {string} secretPolicyName Name of the secret policy that's used to create vault token. - * @param {string} boundaryPolicyName Name of the boundary policy that's used to create vault token. - * @returns {Promise} new credential store's ID - */ -exports.createVaultCredentialStoreCli = async ( - projectId, - vaultAddr, - secretPolicyName, - boundaryPolicyName, -) => { - let credentialStore; - try { - execSync( - `vault policy write ${boundaryPolicyName} ./tests/e2e/tests/fixtures/boundary-controller-policy.hcl`, - ); - 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 credentialStoreName = 'vault-credential-store-' + nanoid(); - credentialStore = JSON.parse( - execSync( - `boundary credential-stores create vault \ - -scope-id ${projectId} \ - -name ${credentialStoreName} \ - -vault-address ${vaultAddr} \ - -vault-token ${clientToken} \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return credentialStore.id; -}; - -/** - * Uses the boundary CLI to create a new username-password credential. - * @param {string} credentialStoreId ID of the credential store that the credential will be created for. - * @returns {Promise} new credential's ID - */ -exports.createUsernamePasswordCredentialCli = async (credentialStoreId) => { - let usernamePasswordCredential; - const login = 'test-login'; - try { - usernamePasswordCredential = JSON.parse( - execSync( - `boundary credentials create username-password \ - -name ${login} \ - -credential-store-id ${credentialStoreId} \ - -username ${login} \ - -password env://CREDENTIALS_PASSWORD \ - -format json`, - { - env: { ...process.env, CREDENTIALS_PASSWORD: 'credentials-password' }, - }, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return usernamePasswordCredential.id; -}; - -/** - * Uses the boundary CLI to create a new TCP target. - * @param {string} projectId ID of the project under which the target will be created. - * @returns {Promise} new target's ID - */ -exports.createTcpTarget = async (projectId) => { - const targetName = 'target-' + nanoid(); - const defaultPort = 22; - let target; - try { - target = JSON.parse( - execSync( - `boundary targets create tcp \ - -default-port ${defaultPort} \ - -name ${targetName} \ - -scope-id ${projectId} \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return target.id; -}; - -/** - * Uses the boundary CLI to create a new SSH target. - * @param {string} projectId ID of the project under which the target will be created. - * @returns {Promise} new target's ID - */ -exports.createSshTargetCli = async (projectId) => { - const targetName = 'target-' + nanoid(); - const defaultPort = 22; - let target; - try { - target = JSON.parse( - execSync( - `boundary targets create ssh \ - -default-port ${defaultPort} \ - -name ${targetName} \ - -scope-id ${projectId} \ - -format json`, - ), - ).item; - } catch (e) { - console.log(`${e.stderr}`); - } - return target.id; -}; - -/** - * 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; -}; - -/** - * Uses the boundary CLI to wait for a session recording to be available. - * @param {string} storageBucketId ID of storage bucket that the session recording is associated with - * @returns An object representing a session recording - */ -exports.waitForSessionRecordingCli = async (storageBucketId) => { - let i = 0; - let filteredSessionRecording = []; - do { - i = i + 1; - const sessionRecordings = JSON.parse( - execSync('boundary session-recordings list --recursive -format json'), - ); - filteredSessionRecording = sessionRecordings.items.filter( - (obj) => - obj.storage_bucket_id == storageBucketId && obj.state == 'available', - ); - if (filteredSessionRecording.length > 0) { - break; - } - await new Promise((resolve) => setTimeout(resolve, 1000)); - } while (i < 5); - - return filteredSessionRecording[0]; -}; diff --git a/ui/admin/tests/e2e/helpers/boundary-cli.mjs b/ui/admin/tests/e2e/helpers/boundary-cli.mjs new file mode 100644 index 000000000..2bfccc2c8 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli.mjs @@ -0,0 +1,37 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; + +export * from './boundary-cli/accounts.mjs'; +export * from './boundary-cli/aliases.mjs'; +export * from './boundary-cli/auth-methods.mjs'; +export * from './boundary-cli/authenticate.mjs'; +export * from './boundary-cli/connect.mjs'; +export * from './boundary-cli/credential-stores.mjs'; +export * from './boundary-cli/credentials.mjs'; +export * from './boundary-cli/groups.mjs'; +export * from './boundary-cli/host-catalogs.mjs'; +export * from './boundary-cli/host-sets.mjs'; +export * from './boundary-cli/hosts.mjs'; +export * from './boundary-cli/policies.mjs'; +export * from './boundary-cli/roles.mjs'; +export * from './boundary-cli/scopes.mjs'; +export * from './boundary-cli/session-recordings.mjs'; +export * from './boundary-cli/storage-buckets.mjs'; +export * from './boundary-cli/targets.mjs'; +export * from './boundary-cli/users.mjs'; +export * from './boundary-cli/workers.mjs'; + +/** + * Checks that the boundary cli is available + */ +export async function checkBoundaryCli() { + try { + execSync('which boundary'); + } catch (e) { + throw new Error('boundary does not exist on the path'); + } +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/accounts.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/accounts.mjs new file mode 100644 index 000000000..cb6f2d7d2 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/accounts.mjs @@ -0,0 +1,31 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; + +/** + * Creates a new password account + * @param {string} authMethodId ID of the auth-method that the new account will be created for. + * @returns {Promise} new account's ID + */ +export async function createPasswordAccountCli(authMethodId) { + let passwordAccount; + const login = 'test-login'; + try { + passwordAccount = JSON.parse( + execSync( + `boundary accounts create password \ + -auth-method-id ${authMethodId} \ + -login-name ${login} \ + -password env://ACCOUNT_PASSWORD \ + -format json`, + { env: { ...process.env, ACCOUNT_PASSWORD: 'test-password' } }, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return passwordAccount.id; +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/aliases.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/aliases.mjs new file mode 100644 index 000000000..5daf6147c --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/aliases.mjs @@ -0,0 +1,21 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; + +/** + * Deletes the specified alias + * @param {string} aliasValue Value of the alias to be deleted + */ +export async function deleteAliasCli(aliasValue) { + try { + const aliases = JSON.parse(execSync('boundary aliases list -format json')); + const alias = aliases.items.filter((obj) => obj.value == aliasValue)[0]; + + execSync('boundary aliases delete -id=' + alias.id); + } catch (e) { + console.log(`${e.stderr}`); + } +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/auth-methods.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/auth-methods.mjs new file mode 100644 index 000000000..6a24c135f --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/auth-methods.mjs @@ -0,0 +1,30 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; +import { nanoid } from 'nanoid'; + +/** + * Creates a new password auth-method + * @param {string} scopeId ID of the scope under which the auth-method will be created. + * @returns {Promise} new auth-method's ID + */ +export async function createPasswordAuthMethodCli(scopeId) { + const authMethodName = 'auth-method-' + nanoid(); + let newAuthMethod; + try { + newAuthMethod = JSON.parse( + execSync( + `boundary auth-methods create password \ + -name "${authMethodName}" \ + -scope-id ${scopeId} \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return newAuthMethod.id; +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/authenticate.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/authenticate.mjs new file mode 100644 index 000000000..fbbbc64f2 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/authenticate.mjs @@ -0,0 +1,33 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; + +/** + * Authenticates to the specified Boundary instance + * @param {string} addr Address of the Boundary instance to be authenticated to + * @param {string} authMethodId ID of the auth method to be used for authentication + * @param {string} loginName Login name to be used for authentication + * @param {string} password Password to be used for authentication + */ +export async function authenticateBoundaryCli( + addr, + authMethodId, + loginName, + password, +) { + try { + execSync( + 'boundary authenticate password' + + ` -addr=${addr}` + + ` -auth-method-id=${authMethodId}` + + ` -login-name=${loginName}` + + ' -password=env://BPASS', + { env: { ...process.env, BPASS: password } }, + ); + } catch (e) { + console.log(`${e.stderr}`); + } +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/connect.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/connect.mjs new file mode 100644 index 000000000..4a22bfdcd --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/connect.mjs @@ -0,0 +1,57 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { exec } from 'node:child_process'; + +/** + * Connects to the specified target + * exec is used here to keep the session open + * @param {string} targetId ID of the target to be connected to + * @param {string} sshUser User to be used for the ssh connection + * @param {string} sshKeyPath Path to the ssh key to be used for the ssh connection + * @returns ChildProcess representing the result of the command execution + */ +export async function connectToTarget(targetId, sshUser, sshKeyPath) { + let connect; + try { + connect = exec( + `boundary connect -target-id=${targetId}` + + ' -exec /usr/bin/ssh --' + + ` -l ${sshUser}` + + ` -i ${sshKeyPath}` + + ' -o UserKnownHostsFile=/dev/null' + + ' -o StrictHostKeyChecking=no' + + ' -o IdentitiesOnly=yes' + // forces the use of the provided key + ' -p {{boundary.port}}' + + ' {{boundary.ip}}', + ); + } catch (e) { + console.log(`${e.stderr}`); + } + return connect; +} + +/** + * Connects via ssh to the specified target + * exec is used here to keep the session open + * @param {string} targetId ID of the target to be connected to + * @returns ChildProcess representing the result of the command execution + */ +export async function connectSshToTarget(targetId) { + let connect; + try { + connect = exec( + 'boundary connect ssh' + + ` -target-id=${targetId}` + + ' --' + + ' -o UserKnownHostsFile=/dev/null' + + ' -o StrictHostKeyChecking=no' + + ' -o IdentitiesOnly=yes', // forces the use of the provided key + ); + } catch (e) { + console.log(`${e.stderr}`); + } + return connect; +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/credential-stores.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/credential-stores.mjs new file mode 100644 index 000000000..73126eee9 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/credential-stores.mjs @@ -0,0 +1,61 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; +import { nanoid } from 'nanoid'; + +/** + * Creates a new static credential store + * @param {string} projectId ID of the project under which the credential store will be created. + * @returns {Promise} new credential store's ID + */ +export async function createStaticCredentialStoreCli(projectId) { + const credentialStoreName = 'static-credential-store-' + nanoid(); + let staticCredentialStore; + try { + staticCredentialStore = JSON.parse( + execSync( + `boundary credential-stores create static \ + -scope-id ${projectId} \ + -name ${credentialStoreName} \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return staticCredentialStore.id; +} + +/** + * Creates a new vault credential store + * @param {string} projectId ID of the project under which the credential store will be created. + * @param {string} vaultAddr Address of the vault that the credential store will be created for. + * @param {string} vaultToken Token for Boundary to authenticate with Vault + * @returns {Promise} new credential store's ID + */ +export async function createVaultCredentialStoreCli( + projectId, + vaultAddr, + vaultToken, +) { + let credentialStore; + try { + const credentialStoreName = 'vault-credential-store-' + nanoid(); + credentialStore = JSON.parse( + execSync( + `boundary credential-stores create vault \ + -scope-id ${projectId} \ + -name ${credentialStoreName} \ + -vault-address ${vaultAddr} \ + -vault-token ${vaultToken} \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return credentialStore.id; +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/credentials.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/credentials.mjs new file mode 100644 index 000000000..4a5dafd1b --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/credentials.mjs @@ -0,0 +1,34 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; + +/** + * Creates a new username-password credential + * @param {string} credentialStoreId ID of the credential store that the credential will be created for. + * @returns {Promise} new credential's ID + */ +export async function createUsernamePasswordCredentialCli(credentialStoreId) { + let usernamePasswordCredential; + const login = 'test-login'; + try { + usernamePasswordCredential = JSON.parse( + execSync( + `boundary credentials create username-password \ + -name ${login} \ + -credential-store-id ${credentialStoreId} \ + -username ${login} \ + -password env://CREDENTIALS_PASSWORD \ + -format json`, + { + env: { ...process.env, CREDENTIALS_PASSWORD: 'credentials-password' }, + }, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return usernamePasswordCredential.id; +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/groups.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/groups.mjs new file mode 100644 index 000000000..200fc7f32 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/groups.mjs @@ -0,0 +1,30 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; +import { nanoid } from 'nanoid'; + +/** + * Creates a new group + * @param {string} scopeId ID of the scope under which the group will be created. + * @returns {Promise} new group's ID + */ +export async function createGroupCli(scopeId) { + const groupName = 'group-' + nanoid(); + let group; + try { + group = JSON.parse( + execSync( + `boundary groups create \ + -scope-id ${scopeId} \ + -name ${groupName} \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return group.id; +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/host-catalogs.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/host-catalogs.mjs new file mode 100644 index 000000000..25bf89901 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/host-catalogs.mjs @@ -0,0 +1,59 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; +import { nanoid } from 'nanoid'; + +/** + * Creates a new static host catalog + * @param {string} projectId ID of the project under which the host catalog will be created. + * @returns {Promise} new host catalog's ID + */ +export async function createStaticHostCatalogCli(projectId) { + const hostCatalogName = 'static-host-catalog-' + nanoid(); + let hostCatalog; + try { + hostCatalog = JSON.parse( + execSync( + `boundary host-catalogs create static \ + -scope-id ${projectId} \ + -name ${hostCatalogName} \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return hostCatalog.id; +} + +/** + * Creates a new dynamic AWS host catalog + * @param {string} projectId ID of the project under which the host catalog will be created. + * @param {string} region Name of the AWS region that the host catalog will be created for. + * @returns {Promise} new host catalog's ID + */ +export async function createDynamicAwsHostCatalogCli(projectId, region) { + const hostCatalogName = 'dynamic-aws-host-catalog-' + nanoid(); + let hostCatalog; + try { + hostCatalog = JSON.parse( + execSync( + `boundary host-catalogs create plugin \ + -name ${hostCatalogName} \ + -scope-id ${projectId} \ + -plugin-name aws \ + -attr disable_credential_rotation=true \ + -attr region=${region} \ + -secret access_key_id=env://E2E_AWS_ACCESS_KEY_ID \ + -secret secret_access_key=env://E2E_AWS_SECRET_ACCESS_KEY \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return hostCatalog.id; +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/host-sets.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/host-sets.mjs new file mode 100644 index 000000000..6d98b1b87 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/host-sets.mjs @@ -0,0 +1,30 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; +import { nanoid } from 'nanoid'; + +/** + * Creates a new static host set + * @param {string} hostCatalogId ID of the host catalog that the host set will be created for. + * @returns {Promise} new host set's ID + */ +export async function createHostSetCli(hostCatalogId) { + const hostSetName = 'static-host-' + nanoid(); + let hostSet; + try { + hostSet = JSON.parse( + execSync( + `boundary host-sets create static \ + -host-catalog-id ${hostCatalogId} \ + -name ${hostSetName} \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return hostSet.id; +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/hosts.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/hosts.mjs new file mode 100644 index 000000000..d7bacc9b2 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/hosts.mjs @@ -0,0 +1,31 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; +import { nanoid } from 'nanoid'; + +/** + * Creates a new static host + * @param {string} hostCatalogId ID of the host catalog that the host will be created for. + * @returns {Promise} new host's ID + */ +export async function createStaticHostCli(hostCatalogId) { + const hostName = 'static-host-' + nanoid(); + let host; + try { + host = JSON.parse( + execSync( + `boundary hosts create static \ + -host-catalog-id ${hostCatalogId} \ + -name ${hostName} \ + -address localhost \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return host.id; +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/policies.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/policies.mjs new file mode 100644 index 000000000..b48d8ce6f --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/policies.mjs @@ -0,0 +1,35 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; + +/** + * Deletes the specified policy + * @param {string} policyId ID of the policy to be deleted + */ +export async function deletePolicyCli(policyId) { + try { + execSync('boundary policies delete -id=' + policyId); + } catch (e) { + console.log(`${e.stderr}`); + } +} + +/** + * Gets Policy ID from Policy Name + * @param {string} scopeId Id of the scope under which the policy exists + * @param {string} policyName Name of the policy + * @returns {Promise} ID of the policy + */ +export async function getPolicyIdFromNameCli(scopeId, policyName) { + const policies = JSON.parse( + execSync(`boundary policies list -scope-id ${scopeId} -format json`), + ); + const policy = policies.items.filter((obj) => obj.name == policyName)[0]; + if (policy) { + return policy.id; + } + return null; +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/roles.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/roles.mjs new file mode 100644 index 000000000..f4e8cf181 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/roles.mjs @@ -0,0 +1,30 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; +import { nanoid } from 'nanoid'; + +/** + * Creates a new role + * @param {string} scopeId ID of the scope under which the role will be created. + * @returns {Promise} new role's ID + */ +export async function createRoleCli(scopeId) { + const roleName = 'role-' + nanoid(); + let role; + try { + role = JSON.parse( + execSync( + `boundary roles create \ + -scope-id ${scopeId} \ + -name ${roleName} \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return role.id; +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/scopes.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/scopes.mjs new file mode 100644 index 000000000..eb102f259 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/scopes.mjs @@ -0,0 +1,113 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; +import { nanoid } from 'nanoid'; + +/** + * Creates an org + * @returns {Promise} new org's id + */ +export async function createOrgCli() { + const orgName = 'Org ' + nanoid(); + let newOrg; + try { + newOrg = JSON.parse( + execSync( + `boundary scopes create \ + -name="${orgName}" \ + -scope-id=global \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return newOrg.id; +} + +/** + * Creates a project + * @param {string} orgId ID of the organization under which the project will be created. + * @returns {Promise} new project's ID + */ +export async function createProjectCli(orgId) { + const projectName = 'Project ' + nanoid(); + let newProject; + try { + newProject = JSON.parse( + execSync( + `boundary scopes create \ + -name="${projectName}" \ + -scope-id=${orgId} \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return newProject.id; +} + +/** + * Deletes the specified scope + * @param {string} scopeId ID of the scope to be deleted + */ +export async function deleteScopeCli(scopeId) { + try { + execSync('boundary scopes delete -id=' + scopeId); + } catch (e) { + console.log(`${e.stderr}`); + } +} + +/** + * Gets Org ID from Org Name + * @param {string} orgName Name of the org + * @returns {Promise} ID of the org + */ +export async function getOrgIdFromNameCli(orgName) { + const orgs = JSON.parse(execSync('boundary scopes list -format json')); + const org = orgs.items.filter((obj) => obj.name == orgName)[0]; + if (org) { + return org.id; + } + return null; +} + +/** + * Gets Project ID from Project Name + * @param {string} orgId Id of the org under which the project exists + * @param {string} projectName Name of the project + * @returns {Promise} ID of the project + */ +export async function getProjectIdFromNameCli(orgId, projectName) { + const projects = JSON.parse( + execSync(`boundary scopes list -scope-id ${orgId} -format json`), + ); + const project = projects.items.filter((obj) => obj.name == projectName)[0]; + if (project) { + return project.id; + } + return null; +} + +/** + * Makes an auth-method primary. + * @param {string} scopeId ID of the scope that the auth-method belongs to + * @param {string} authMethodId ID of the auth method that will be made primary + */ +export async function makeAuthMethodPrimaryCli(scopeId, authMethodId) { + try { + execSync( + `boundary scopes update \ + -id=${scopeId} \ + -primary-auth-method-id ${authMethodId} \ + -format json`, + ); + } catch (e) { + console.log(`${e.stderr}`); + } +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/session-recordings.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/session-recordings.mjs new file mode 100644 index 000000000..54ab2dd46 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/session-recordings.mjs @@ -0,0 +1,32 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; + +/** + * Waits for a session recording to be available + * @param {string} storageBucketId ID of storage bucket that the session recording is associated with + * @returns An object representing a session recording + */ +export async function waitForSessionRecordingCli(storageBucketId) { + let i = 0; + let filteredSessionRecording = []; + do { + i = i + 1; + const sessionRecordings = JSON.parse( + execSync('boundary session-recordings list --recursive -format json'), + ); + filteredSessionRecording = sessionRecordings.items.filter( + (obj) => + obj.storage_bucket_id == storageBucketId && obj.state == 'available', + ); + if (filteredSessionRecording.length > 0) { + break; + } + await new Promise((resolve) => setTimeout(resolve, 1000)); + } while (i < 5); + + return filteredSessionRecording[0]; +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/storage-buckets.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/storage-buckets.mjs new file mode 100644 index 000000000..3abf104d8 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/storage-buckets.mjs @@ -0,0 +1,18 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; + +/** + * Deletes the specified storage bucket + * @param {string} storageBucketId ID of the storage bucket to be deleted + */ +export async function deleteStorageBucketCli(storageBucketId) { + try { + execSync('boundary storage-buckets delete -id=' + storageBucketId); + } catch (e) { + console.log(`${e.stderr}`); + } +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/targets.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/targets.mjs new file mode 100644 index 000000000..dc89f5187 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/targets.mjs @@ -0,0 +1,110 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; +import { nanoid } from 'nanoid'; + +/** + * Creates a TCP target. + * @param {string} projectId ID of the project under which the target will be created. + * @returns {Promise} new target's ID + */ +export async function createTcpTarget(projectId) { + const targetName = 'target-' + nanoid(); + const defaultPort = 22; + let target; + try { + target = JSON.parse( + execSync( + `boundary targets create tcp \ + -default-port ${defaultPort} \ + -name ${targetName} \ + -scope-id ${projectId} \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return target.id; +} + +/** + * Creates a SSH target + * @param {string} projectId ID of the project under which the target will be created. + * @returns {Promise} new target's ID + */ +export async function createSshTargetCli(projectId) { + const targetName = 'target-' + nanoid(); + const defaultPort = 22; + let target; + try { + target = JSON.parse( + execSync( + `boundary targets create ssh \ + -default-port ${defaultPort} \ + -name ${targetName} \ + -scope-id ${projectId} \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return target.id; +} + +/** + * Authorizes a session given an alias + * @param {string} alias alias of the target to be connected to + * @returns Session information + */ +export async function authorizeSessionByAliasCli(alias) { + let session; + try { + session = JSON.parse( + execSync(`boundary targets authorize-session ${alias} -format json`), + ); + } catch (e) { + throw new Error(`Failed to connect to alias: ${e.stderr}`); + } + return session; +} + +/** + * Authorizes a session given a target id + * @param {string} targetId Id of the target to be connected to + * @returns Session information + */ +export async function authorizeSessionByTargetIdCli(targetId) { + let session; + try { + session = JSON.parse( + execSync( + `boundary targets authorize-session -id ${targetId} -format json`, + ), + ); + } catch (e) { + throw new Error(`Failed to connect to target: ${e.stderr}`); + } + return session; +} + +/** + * Gets Target ID from Target Name + * @param {string} projectId ID of the project under which the target exists + * @param {string} targetName Name of the target + * @returns {Promise} ID of the target + */ +export async function getTargetIdFromNameCli(projectId, targetName) { + const targets = JSON.parse( + execSync(`boundary targets list -scope-id ${projectId} -format json`), + ); + const target = targets.items.filter((obj) => obj.name == targetName)[0]; + if (target) { + return target.id; + } + return null; +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/users.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/users.mjs new file mode 100644 index 000000000..8c2df2156 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/users.mjs @@ -0,0 +1,30 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; +import { nanoid } from 'nanoid'; + +/** + * Creates a new user. + * @param {string} scopeId ID of the scope under which the user will be created. + * @returns {Promise} new user's ID + */ +export async function createUserCli(scopeId) { + const userName = 'user-' + nanoid(); + let user; + try { + user = JSON.parse( + execSync( + `boundary users create \ + -scope-id ${scopeId} \ + -name ${userName} \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return user.id; +} diff --git a/ui/admin/tests/e2e/helpers/boundary-cli/workers.mjs b/ui/admin/tests/e2e/helpers/boundary-cli/workers.mjs new file mode 100644 index 000000000..12a4a9756 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/boundary-cli/workers.mjs @@ -0,0 +1,28 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; +import { nanoid } from 'nanoid'; + +/** + * Creates a new controller-led worker + * @returns {Promise} new worker's ID + */ +export async function createControllerLedWorkerCli() { + const workerName = 'worker-' + nanoid(); + let newWorker; + try { + newWorker = JSON.parse( + execSync( + `boundary workers create controller-led \ + -name="${workerName.toLowerCase()}" \ + -format json`, + ), + ).item; + } catch (e) { + console.log(`${e.stderr}`); + } + return newWorker.id; +} diff --git a/ui/admin/tests/e2e/helpers/general.js b/ui/admin/tests/e2e/helpers/general.mjs similarity index 77% rename from ui/admin/tests/e2e/helpers/general.js rename to ui/admin/tests/e2e/helpers/general.mjs index 52117ddbd..1cc559f44 100644 --- a/ui/admin/tests/e2e/helpers/general.js +++ b/ui/admin/tests/e2e/helpers/general.mjs @@ -3,13 +3,11 @@ * SPDX-License-Identifier: BUSL-1.1 */ -exports.authenticatedState = './tests/e2e/artifacts/authenticated-state.json'; - /** * Checks that the provided environment variables are set * @param {string[]} envs List of environment variables */ -exports.checkEnv = async (envs) => { +export async function checkEnv(envs) { let missing = []; for (let env in envs) { if (!process.env[envs[env]]) { @@ -20,4 +18,4 @@ exports.checkEnv = async (envs) => { if (missing.length > 0) { throw new Error('Missing Environment Variables -- ' + missing); } -}; +} diff --git a/ui/admin/tests/e2e/helpers/vault-cli.js b/ui/admin/tests/e2e/helpers/vault-cli.js deleted file mode 100644 index 212f1c236..000000000 --- a/ui/admin/tests/e2e/helpers/vault-cli.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -const { execSync } = require('child_process'); - -/** - * Checks that the vault cli is available - */ -exports.checkVaultCli = async () => { - try { - execSync('which vault'); - } catch (e) { - throw new Error('vault does not exist on the path'); - } -}; diff --git a/ui/admin/tests/e2e/helpers/vault-cli.mjs b/ui/admin/tests/e2e/helpers/vault-cli.mjs new file mode 100644 index 000000000..a744a4d39 --- /dev/null +++ b/ui/admin/tests/e2e/helpers/vault-cli.mjs @@ -0,0 +1,52 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { execSync } from 'node:child_process'; + +/** + * Checks that the vault cli is available + */ +export async function checkVaultCli() { + try { + execSync('which vault'); + } catch (e) { + throw new Error('vault does not exist on the path'); + } +} + +/** + * Generates a vault token to be used to integrate with Boundary + * @param {string} boundaryPolicyName Name of the boundary policy that's used to create vault token. + * @param {string} secretPolicyName Name of the secret policy that's used to create vault token. + * @returns {Promise} Vault Token + */ +export async function getVaultToken(boundaryPolicyName, secretPolicyName) { + let clientToken; + try { + execSync( + `vault policy write ${boundaryPolicyName} ./tests/e2e/tests/fixtures/boundary-controller-policy.hcl`, + ); + 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`, + ), + ); + clientToken = vaultToken.auth.client_token; + } catch (e) { + console.log(`${e.stderr}`); + } + + return clientToken; +} diff --git a/ui/admin/tests/e2e/pages/aliases.js b/ui/admin/tests/e2e/pages/aliases.mjs similarity index 87% rename from ui/admin/tests/e2e/pages/aliases.js rename to ui/admin/tests/e2e/pages/aliases.mjs index 4afb65f02..d91ca1c48 100644 --- a/ui/admin/tests/e2e/pages/aliases.js +++ b/ui/admin/tests/e2e/pages/aliases.mjs @@ -3,12 +3,12 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); -const { nanoid } = require('nanoid'); +import { expect } from '@playwright/test'; +import { nanoid } from 'nanoid'; -const BaseResourcePage = require('./base-resource'); +import { BaseResourcePage } from './base-resource.mjs'; -class AliasesPage extends BaseResourcePage { +export class AliasesPage extends BaseResourcePage { /** * Creates an alias * @param {string} alias Value of the alias @@ -55,5 +55,3 @@ class AliasesPage extends BaseResourcePage { return aliasName; } } - -module.exports = AliasesPage; diff --git a/ui/admin/tests/e2e/pages/auth-methods.js b/ui/admin/tests/e2e/pages/auth-methods.mjs similarity index 93% rename from ui/admin/tests/e2e/pages/auth-methods.js rename to ui/admin/tests/e2e/pages/auth-methods.mjs index a7e82e429..4c5759858 100644 --- a/ui/admin/tests/e2e/pages/auth-methods.js +++ b/ui/admin/tests/e2e/pages/auth-methods.mjs @@ -3,12 +3,12 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); -const { nanoid } = require('nanoid'); +import { expect } from '@playwright/test'; +import { nanoid } from 'nanoid'; -const BaseResourcePage = require('./base-resource'); +import { BaseResourcePage } from './base-resource.mjs'; -class AuthMethodsPage extends BaseResourcePage { +export class AuthMethodsPage extends BaseResourcePage { /** * Creates a new Password Auth Method. Assumes you have selected the desired scope. * @returns Name of the auth method @@ -98,5 +98,3 @@ class AuthMethodsPage extends BaseResourcePage { await this.dismissSuccessAlert(); } } - -module.exports = AuthMethodsPage; diff --git a/ui/admin/tests/e2e/pages/base-resource.js b/ui/admin/tests/e2e/pages/base-resource.mjs similarity index 74% rename from ui/admin/tests/e2e/pages/base-resource.js rename to ui/admin/tests/e2e/pages/base-resource.mjs index d09419037..a2370ab4d 100644 --- a/ui/admin/tests/e2e/pages/base-resource.js +++ b/ui/admin/tests/e2e/pages/base-resource.mjs @@ -3,9 +3,9 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const BasePage = require('./base'); +import { BasePage } from './base.mjs'; -class BaseResourcePage extends BasePage { +export class BaseResourcePage extends BasePage { async deleteResource() { await this.page.getByText('Manage').click(); await this.page.getByRole('button', { name: 'Delete' }).click(); @@ -13,5 +13,3 @@ class BaseResourcePage extends BasePage { await this.dismissSuccessAlert(); } } - -module.exports = BaseResourcePage; diff --git a/ui/admin/tests/e2e/pages/base.js b/ui/admin/tests/e2e/pages/base.mjs similarity index 79% rename from ui/admin/tests/e2e/pages/base.js rename to ui/admin/tests/e2e/pages/base.mjs index dc268dde0..1cc7bfedc 100644 --- a/ui/admin/tests/e2e/pages/base.js +++ b/ui/admin/tests/e2e/pages/base.mjs @@ -3,9 +3,9 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); +import { expect } from '@playwright/test'; -class BasePage { +export class BasePage { constructor(page) { this.page = page; } @@ -17,5 +17,3 @@ class BasePage { await this.page.getByRole('button', { name: 'Dismiss' }).click(); } } - -module.exports = BasePage; diff --git a/ui/admin/tests/e2e/pages/credential-stores.js b/ui/admin/tests/e2e/pages/credential-stores.mjs similarity index 97% rename from ui/admin/tests/e2e/pages/credential-stores.js rename to ui/admin/tests/e2e/pages/credential-stores.mjs index 541a1909c..6a12782fc 100644 --- a/ui/admin/tests/e2e/pages/credential-stores.js +++ b/ui/admin/tests/e2e/pages/credential-stores.mjs @@ -3,13 +3,13 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); -const { nanoid } = require('nanoid'); -const { readFile } = require('fs/promises'); +import { expect } from '@playwright/test'; +import { nanoid } from 'nanoid'; +import { readFile } from 'fs/promises'; -const BaseResourcePage = require('./base-resource'); +import { BaseResourcePage } from './base-resource.mjs'; -class CredentialStoresPage extends BaseResourcePage { +export class CredentialStoresPage extends BaseResourcePage { /** * Creates a static credential store. Assumes you have selected the desired project. * @returns Name of the credential store @@ -258,5 +258,3 @@ class CredentialStoresPage extends BaseResourcePage { return credentialLibraryName; } } - -module.exports = CredentialStoresPage; diff --git a/ui/admin/tests/e2e/pages/groups.js b/ui/admin/tests/e2e/pages/groups.mjs similarity index 87% rename from ui/admin/tests/e2e/pages/groups.js rename to ui/admin/tests/e2e/pages/groups.mjs index 0a9cb5ed9..aac1ca4a4 100644 --- a/ui/admin/tests/e2e/pages/groups.js +++ b/ui/admin/tests/e2e/pages/groups.mjs @@ -3,12 +3,12 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); -const { nanoid } = require('nanoid'); +import { expect } from '@playwright/test'; +import { nanoid } from 'nanoid'; -const BaseResourcePage = require('./base-resource'); +import { BaseResourcePage } from './base-resource.mjs'; -class GroupsPage extends BaseResourcePage { +export class GroupsPage extends BaseResourcePage { /** * Creates a new group. Assumes you have selected the desired scope. * @returns Name of the group @@ -52,5 +52,3 @@ class GroupsPage extends BaseResourcePage { ).toBeVisible(); } } - -module.exports = GroupsPage; diff --git a/ui/admin/tests/e2e/pages/host-catalogs.js b/ui/admin/tests/e2e/pages/host-catalogs.mjs similarity index 93% rename from ui/admin/tests/e2e/pages/host-catalogs.js rename to ui/admin/tests/e2e/pages/host-catalogs.mjs index 31ebdbfc0..afdf02640 100644 --- a/ui/admin/tests/e2e/pages/host-catalogs.js +++ b/ui/admin/tests/e2e/pages/host-catalogs.mjs @@ -3,12 +3,12 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); -const { nanoid } = require('nanoid'); +import { expect } from '@playwright/test'; +import { nanoid } from 'nanoid'; -const BaseResourcePage = require('./base-resource'); +import { BaseResourcePage } from './base-resource.mjs'; -class HostCatalogsPage extends BaseResourcePage { +export class HostCatalogsPage extends BaseResourcePage { /** * Creates a new host catalog. Assumes you have selected the desired project. * @returns Name of the host catalog @@ -106,5 +106,3 @@ class HostCatalogsPage extends BaseResourcePage { return hostName; } } - -module.exports = HostCatalogsPage; diff --git a/ui/admin/tests/e2e/pages/orgs.js b/ui/admin/tests/e2e/pages/orgs.mjs similarity index 88% rename from ui/admin/tests/e2e/pages/orgs.js rename to ui/admin/tests/e2e/pages/orgs.mjs index 74311a225..256c2769b 100644 --- a/ui/admin/tests/e2e/pages/orgs.js +++ b/ui/admin/tests/e2e/pages/orgs.mjs @@ -3,12 +3,12 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); -const { nanoid } = require('nanoid'); +import { expect } from '@playwright/test'; +import { nanoid } from 'nanoid'; -const BaseResourcePage = require('./base-resource'); +import { BaseResourcePage } from './base-resource.mjs'; -class OrgsPage extends BaseResourcePage { +export class OrgsPage extends BaseResourcePage { /** * Creates a new organization * @returns Name of the organization @@ -52,5 +52,3 @@ class OrgsPage extends BaseResourcePage { ).toBeVisible(); } } - -module.exports = OrgsPage; diff --git a/ui/admin/tests/e2e/pages/projects.js b/ui/admin/tests/e2e/pages/projects.mjs similarity index 80% rename from ui/admin/tests/e2e/pages/projects.js rename to ui/admin/tests/e2e/pages/projects.mjs index 7dd8429c8..1bbf818b0 100644 --- a/ui/admin/tests/e2e/pages/projects.js +++ b/ui/admin/tests/e2e/pages/projects.mjs @@ -3,12 +3,12 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); -const { nanoid } = require('nanoid'); +import { expect } from '@playwright/test'; +import { nanoid } from 'nanoid'; -const BaseResourcePage = require('./base-resource'); +import { BaseResourcePage } from './base-resource.mjs'; -class ProjectsPage extends BaseResourcePage { +export class ProjectsPage extends BaseResourcePage { /** * Creates a new project. Assumes you have selected the desired org. * @returns Name of the project @@ -33,5 +33,3 @@ class ProjectsPage extends BaseResourcePage { return projectName; } } - -module.exports = ProjectsPage; diff --git a/ui/admin/tests/e2e/pages/roles.js b/ui/admin/tests/e2e/pages/roles.mjs similarity index 91% rename from ui/admin/tests/e2e/pages/roles.js rename to ui/admin/tests/e2e/pages/roles.mjs index 0f1ef530f..39e1193ce 100644 --- a/ui/admin/tests/e2e/pages/roles.js +++ b/ui/admin/tests/e2e/pages/roles.mjs @@ -3,12 +3,12 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); -const { nanoid } = require('nanoid'); +import { expect } from '@playwright/test'; +import { nanoid } from 'nanoid'; -const BaseResourcePage = require('./base-resource'); +import { BaseResourcePage } from './base-resource.mjs'; -class RolesPage extends BaseResourcePage { +export class RolesPage extends BaseResourcePage { /** * Creates a new role. Assumes you have selected the desired scope. */ @@ -72,5 +72,3 @@ class RolesPage extends BaseResourcePage { ).toHaveValue(grants); } } - -module.exports = RolesPage; diff --git a/ui/admin/tests/e2e/pages/sessions.js b/ui/admin/tests/e2e/pages/sessions.mjs similarity index 90% rename from ui/admin/tests/e2e/pages/sessions.js rename to ui/admin/tests/e2e/pages/sessions.mjs index a92d7f054..c5a89258e 100644 --- a/ui/admin/tests/e2e/pages/sessions.js +++ b/ui/admin/tests/e2e/pages/sessions.mjs @@ -3,11 +3,11 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); +import { expect } from '@playwright/test'; -const BasePage = require('./base'); +import { BasePage } from './base.mjs'; -class SessionsPage extends BasePage { +export class SessionsPage extends BasePage { /** * Waits for the session to appear and be in Active state. * @param {string} targetName Name of the target associated with the session @@ -56,5 +56,3 @@ class SessionsPage extends BasePage { } } } - -module.exports = SessionsPage; diff --git a/ui/admin/tests/e2e/pages/storage-buckets.js b/ui/admin/tests/e2e/pages/storage-buckets.mjs similarity index 94% rename from ui/admin/tests/e2e/pages/storage-buckets.js rename to ui/admin/tests/e2e/pages/storage-buckets.mjs index 8091f170f..ac9cc136e 100644 --- a/ui/admin/tests/e2e/pages/storage-buckets.js +++ b/ui/admin/tests/e2e/pages/storage-buckets.mjs @@ -3,12 +3,12 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); -const { nanoid } = require('nanoid'); +import { expect } from '@playwright/test'; +import { nanoid } from 'nanoid'; -const BaseResourcePage = require('./base-resource'); +import { BaseResourcePage } from './base-resource.mjs'; -class StorageBucketsPage extends BaseResourcePage { +export class StorageBucketsPage extends BaseResourcePage { /** * Creates a new AWS Storage Bucket. * @param {string} scope Scope of the Storage Bucket @@ -104,5 +104,3 @@ class StorageBucketsPage extends BaseResourcePage { return storageBucketName; } } - -module.exports = StorageBucketsPage; diff --git a/ui/admin/tests/e2e/pages/storage-policies.js b/ui/admin/tests/e2e/pages/storage-policies.mjs similarity index 86% rename from ui/admin/tests/e2e/pages/storage-policies.js rename to ui/admin/tests/e2e/pages/storage-policies.mjs index 44c97a65c..5a38a4d0e 100644 --- a/ui/admin/tests/e2e/pages/storage-policies.js +++ b/ui/admin/tests/e2e/pages/storage-policies.mjs @@ -3,12 +3,12 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); -const { nanoid } = require('nanoid'); +import { expect } from '@playwright/test'; +import { nanoid } from 'nanoid'; -const BaseResourcePage = require('./base-resource'); +import { BaseResourcePage } from './base-resource.mjs'; -class StoragePoliciesPage extends BaseResourcePage { +export class StoragePoliciesPage extends BaseResourcePage { /** * Creates a Storage Policy. Assumes you have selected the desired scope. * @returns Name of the Storage Policy @@ -52,5 +52,3 @@ class StoragePoliciesPage extends BaseResourcePage { return storagePolicyName; } } - -module.exports = StoragePoliciesPage; diff --git a/ui/admin/tests/e2e/pages/targets.js b/ui/admin/tests/e2e/pages/targets.mjs similarity index 98% rename from ui/admin/tests/e2e/pages/targets.js rename to ui/admin/tests/e2e/pages/targets.mjs index 3d4ed5f10..4a2ecbebd 100644 --- a/ui/admin/tests/e2e/pages/targets.js +++ b/ui/admin/tests/e2e/pages/targets.mjs @@ -3,12 +3,12 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); -const { nanoid } = require('nanoid'); +import { expect } from '@playwright/test'; +import { nanoid } from 'nanoid'; -const BaseResourcePage = require('./base-resource'); +import { BaseResourcePage } from './base-resource.mjs'; -class TargetsPage extends BaseResourcePage { +export class TargetsPage extends BaseResourcePage { /** * Creates a new target. Assumes you have selected the desired project. * @param {string} port Port of the target @@ -442,5 +442,3 @@ class TargetsPage extends BaseResourcePage { ).toBeVisible(); } } - -module.exports = TargetsPage; diff --git a/ui/admin/tests/e2e/pages/users.js b/ui/admin/tests/e2e/pages/users.mjs similarity index 87% rename from ui/admin/tests/e2e/pages/users.js rename to ui/admin/tests/e2e/pages/users.mjs index a8827623e..6147b4209 100644 --- a/ui/admin/tests/e2e/pages/users.js +++ b/ui/admin/tests/e2e/pages/users.mjs @@ -3,12 +3,12 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); -const { nanoid } = require('nanoid'); +import { expect } from '@playwright/test'; +import { nanoid } from 'nanoid'; -const BaseResourcePage = require('./base-resource'); +import { BaseResourcePage } from './base-resource.mjs'; -class UsersPage extends BaseResourcePage { +export class UsersPage extends BaseResourcePage { /** * Creates a new user. * @returns Name of the user @@ -58,5 +58,3 @@ class UsersPage extends BaseResourcePage { await this.dismissSuccessAlert(); } } - -module.exports = UsersPage; diff --git a/ui/admin/tests/e2e/pages/workers.js b/ui/admin/tests/e2e/pages/workers.mjs similarity index 72% rename from ui/admin/tests/e2e/pages/workers.js rename to ui/admin/tests/e2e/pages/workers.mjs index 95865b6e8..7aeda8c03 100644 --- a/ui/admin/tests/e2e/pages/workers.js +++ b/ui/admin/tests/e2e/pages/workers.mjs @@ -3,9 +3,9 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const BaseResourcePage = require('./base-resource'); +import { BaseResourcePage } from './base-resource.mjs'; -class WorkersPage extends BaseResourcePage { +export class WorkersPage extends BaseResourcePage { async deleteResource() { await this.page.getByText('Manage').click(); await this.page.getByRole('button', { name: 'Remove Worker' }).click(); @@ -13,5 +13,3 @@ class WorkersPage extends BaseResourcePage { await this.dismissSuccessAlert(); } } - -module.exports = WorkersPage; diff --git a/ui/admin/tests/e2e/playwright.config.js b/ui/admin/tests/e2e/playwright.config.mjs similarity index 85% rename from ui/admin/tests/e2e/playwright.config.js rename to ui/admin/tests/e2e/playwright.config.mjs index 931588f71..862d67f9c 100644 --- a/ui/admin/tests/e2e/playwright.config.js +++ b/ui/admin/tests/e2e/playwright.config.mjs @@ -3,11 +3,11 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { devices } = require('@playwright/test'); +import { defineConfig, devices } from '@playwright/test'; /** @type {import('@playwright/test').PlaywrightTestConfig} */ -const config = { - globalSetup: require.resolve('./global-setup'), +export default defineConfig({ + globalSetup: './global-setup', outputDir: './artifacts/test-failures', timeout: 90000, // Each test is given 90s to complete workers: 1, // Tests need to be run in serial, otherwise there may be conflicts when using the CLI @@ -34,6 +34,4 @@ const config = { use: { ...devices['Desktop Safari'] }, }, ], -}; - -module.exports = config; +}); diff --git a/ui/admin/tests/e2e/tests/alias-ent.spec.js b/ui/admin/tests/e2e/tests/alias-ent.spec.mjs similarity index 79% rename from ui/admin/tests/e2e/tests/alias-ent.spec.js rename to ui/admin/tests/e2e/tests/alias-ent.spec.mjs index b1a150a62..ae09e9c03 100644 --- a/ui/admin/tests/e2e/tests/alias-ent.spec.js +++ b/ui/admin/tests/e2e/tests/alias-ent.spec.mjs @@ -3,23 +3,26 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test, expect } = require('@playwright/test'); -import { execSync } from 'child_process'; +import { test, expect } from '@playwright/test'; import { customAlphabet } from 'nanoid'; -const { checkEnv, authenticatedState } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, - authorizeAlias, + authorizeSessionByAliasCli, checkBoundaryCli, deleteAliasCli, - deleteOrgCli, -} = require('../helpers/boundary-cli'); -const AliasesPage = require('../pages/aliases'); -const CredentialStoresPage = require('../pages/credential-stores'); -const OrgsPage = require('../pages/orgs'); -const ProjectsPage = require('../pages/projects'); -const TargetsPage = require('../pages/targets'); + deleteScopeCli, + getOrgIdFromNameCli, + getProjectIdFromNameCli, + getTargetIdFromNameCli, +} from '../helpers/boundary-cli.mjs'; +import { AliasesPage } from '../pages/aliases.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'; test.use({ storageState: authenticatedState }); @@ -89,7 +92,7 @@ test.describe('Aliases (Enterprise)', async () => { process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - await authorizeAlias(alias); + await authorizeSessionByAliasCli(alias); // Clear destination from alias await page.getByRole('link', { name: alias }).click(); @@ -108,10 +111,9 @@ test.describe('Aliases (Enterprise)', async () => { process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); if (orgName) { - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - if (org) { - await deleteOrgCli(org.id); + const orgId = await getOrgIdFromNameCli(orgName); + if (orgId) { + await deleteScopeCli(orgId); } } if (alias) { @@ -158,7 +160,7 @@ test.describe('Aliases (Enterprise)', async () => { ); // Connect to target using alias - await authorizeAlias(alias); + await authorizeSessionByAliasCli(alias); } finally { await authenticateBoundaryCli( process.env.BOUNDARY_ADDR, @@ -168,10 +170,9 @@ test.describe('Aliases (Enterprise)', async () => { ); if (orgName) { - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - if (org) { - await deleteOrgCli(org.id); + const orgId = await getOrgIdFromNameCli(orgName); + if (orgId) { + await deleteScopeCli(orgId); } if (alias) { await deleteAliasCli(alias); @@ -183,7 +184,7 @@ test.describe('Aliases (Enterprise)', async () => { test('Set up alias from aliases page @ent @aws @docker', async ({ page }) => { await page.goto('/'); const nanoid = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz', 10); - let org; + let orgId; let alias; try { const orgsPage = new OrgsPage(page); @@ -214,24 +215,14 @@ test.describe('Aliases (Enterprise)', async () => { process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - 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]; + orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); alias = 'example.alias.' + nanoid(); const aliasesPage = new AliasesPage(page); - await aliasesPage.createAliasForTarget(alias, target.id); - await authorizeAlias(alias); + await aliasesPage.createAliasForTarget(alias, targetId); + await authorizeSessionByAliasCli(alias); } finally { await authenticateBoundaryCli( process.env.BOUNDARY_ADDR, @@ -240,8 +231,8 @@ test.describe('Aliases (Enterprise)', async () => { process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - if (org) { - await deleteOrgCli(org.id); + if (orgId) { + await deleteScopeCli(orgId); } if (alias) { await deleteAliasCli(alias); diff --git a/ui/admin/tests/e2e/tests/alias.spec.js b/ui/admin/tests/e2e/tests/alias.spec.mjs similarity index 76% rename from ui/admin/tests/e2e/tests/alias.spec.js rename to ui/admin/tests/e2e/tests/alias.spec.mjs index 79bd05808..8b20c6f03 100644 --- a/ui/admin/tests/e2e/tests/alias.spec.js +++ b/ui/admin/tests/e2e/tests/alias.spec.mjs @@ -3,22 +3,25 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test, expect } = require('@playwright/test'); -import { execSync } from 'child_process'; +import { test, expect } from '@playwright/test'; import { customAlphabet } from 'nanoid'; -const { checkEnv, authenticatedState } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, - authorizeAlias, + authorizeSessionByAliasCli, checkBoundaryCli, deleteAliasCli, - deleteOrgCli, -} = require('../helpers/boundary-cli'); -const AliasesPage = require('../pages/aliases'); -const OrgsPage = require('../pages/orgs'); -const ProjectsPage = require('../pages/projects'); -const TargetsPage = require('../pages/targets'); + deleteScopeCli, + getOrgIdFromNameCli, + getProjectIdFromNameCli, + getTargetIdFromNameCli, +} from '../helpers/boundary-cli.mjs'; +import { AliasesPage } from '../pages/aliases.mjs'; +import { OrgsPage } from '../pages/orgs.mjs'; +import { ProjectsPage } from '../pages/projects.mjs'; +import { TargetsPage } from '../pages/targets.mjs'; test.use({ storageState: authenticatedState }); @@ -72,7 +75,7 @@ test.describe('Aliases', async () => { process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - await authorizeAlias(alias); + await authorizeSessionByAliasCli(alias); // Clear destination from alias await page.getByRole('link', { name: alias }).click(); @@ -91,10 +94,9 @@ test.describe('Aliases', async () => { process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); if (orgName) { - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - if (org) { - await deleteOrgCli(org.id); + const orgId = await getOrgIdFromNameCli(orgName); + if (orgId) { + await deleteScopeCli(orgId); } } if (alias) { @@ -130,7 +132,7 @@ test.describe('Aliases', async () => { ); // Connect to target using alias - await authorizeAlias(alias); + await authorizeSessionByAliasCli(alias); } finally { await authenticateBoundaryCli( process.env.BOUNDARY_ADDR, @@ -138,12 +140,10 @@ test.describe('Aliases', async () => { process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - if (orgName) { - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - if (org) { - await deleteOrgCli(org.id); + const orgId = await getOrgIdFromNameCli(orgName); + if (orgId) { + await deleteScopeCli(orgId); } if (alias) { await deleteAliasCli(alias); @@ -155,7 +155,7 @@ test.describe('Aliases', async () => { test('Set up alias from aliases page @ce @aws @docker', async ({ page }) => { await page.goto('/'); const nanoid = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz', 10); - let org; + let orgId; let alias; try { const orgsPage = new OrgsPage(page); @@ -175,24 +175,14 @@ test.describe('Aliases', async () => { process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - 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]; + orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); alias = 'example.alias.' + nanoid(); const aliasesPage = new AliasesPage(page); - await aliasesPage.createAliasForTarget(alias, target.id); - await authorizeAlias(alias); + await aliasesPage.createAliasForTarget(alias, targetId); + await authorizeSessionByAliasCli(alias); } finally { await authenticateBoundaryCli( process.env.BOUNDARY_ADDR, @@ -200,9 +190,8 @@ test.describe('Aliases', async () => { process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - - if (org) { - await deleteOrgCli(org.id); + if (orgId) { + await deleteScopeCli(orgId); } if (alias) { await deleteAliasCli(alias); diff --git a/ui/admin/tests/e2e/tests/auth-method-ldap.spec.js b/ui/admin/tests/e2e/tests/auth-method-ldap.spec.mjs similarity index 94% rename from ui/admin/tests/e2e/tests/auth-method-ldap.spec.js rename to ui/admin/tests/e2e/tests/auth-method-ldap.spec.mjs index f602b7e55..e849a1635 100644 --- a/ui/admin/tests/e2e/tests/auth-method-ldap.spec.js +++ b/ui/admin/tests/e2e/tests/auth-method-ldap.spec.mjs @@ -3,20 +3,20 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test, expect } = require('@playwright/test'); -const { execSync } = require('child_process'); -const { nanoid } = require('nanoid'); +import { test, expect } from '@playwright/test'; +import { nanoid } from 'nanoid'; -const { checkEnv } = require('../helpers/general'); -const { +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, checkBoundaryCli, - deleteOrgCli, -} = require('../helpers/boundary-cli'); -const AuthMethodsPage = require('../pages/auth-methods'); -const OrgsPage = require('../pages/orgs'); -const RolesPage = require('../pages/roles'); -const UsersPage = require('../pages/users'); + deleteScopeCli, + getOrgIdFromNameCli, +} from '../helpers/boundary-cli.mjs'; +import { AuthMethodsPage } from '../pages/auth-methods.mjs'; +import { OrgsPage } from '../pages/orgs.mjs'; +import { RolesPage } from '../pages/roles.mjs'; +import { UsersPage } from '../pages/users.mjs'; test.beforeAll(async () => { await checkEnv([ @@ -294,10 +294,9 @@ test('Set up LDAP auth method @ce @ent @docker', async ({ page }) => { process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - if (org) { - await deleteOrgCli(org.id); + const orgId = await getOrgIdFromNameCli(orgName); + if (orgId) { + await deleteScopeCli(orgId); } } } diff --git a/ui/admin/tests/e2e/tests/auth-method-password.spec.js b/ui/admin/tests/e2e/tests/auth-method-password.spec.mjs similarity index 91% rename from ui/admin/tests/e2e/tests/auth-method-password.spec.js rename to ui/admin/tests/e2e/tests/auth-method-password.spec.mjs index a06b3a9ad..f8c299d06 100644 --- a/ui/admin/tests/e2e/tests/auth-method-password.spec.js +++ b/ui/admin/tests/e2e/tests/auth-method-password.spec.mjs @@ -3,17 +3,18 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test, expect } = require('@playwright/test'); -const { execSync } = require('child_process'); +import { test, expect } from '@playwright/test'; +import { execSync } from 'node:child_process'; -const { +import { authenticateBoundaryCli, checkBoundaryCli, - deleteOrgCli, -} = require('../helpers/boundary-cli'); -const AuthMethodsPage = require('../pages/auth-methods'); -const OrgsPage = require('../pages/orgs'); -const UsersPage = require('../pages/users'); + deleteScopeCli, + getOrgIdFromNameCli, +} from '../helpers/boundary-cli.mjs'; +import { AuthMethodsPage } from '../pages/auth-methods.mjs'; +import { OrgsPage } from '../pages/orgs.mjs'; +import { UsersPage } from '../pages/users.mjs'; test.beforeAll(async () => { await checkBoundaryCli(); @@ -162,10 +163,9 @@ test('Verify new auth-method can be created and assigned to users @ce @ent @aws } if (orgName) { - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - if (org) { - await deleteOrgCli(org.id); + const orgId = await getOrgIdFromNameCli(orgName); + if (orgId) { + await deleteScopeCli(orgId); } } } diff --git a/ui/admin/tests/e2e/tests/credential-store-static-ent.spec.js b/ui/admin/tests/e2e/tests/credential-store-static-ent.spec.mjs similarity index 82% rename from ui/admin/tests/e2e/tests/credential-store-static-ent.spec.js rename to ui/admin/tests/e2e/tests/credential-store-static-ent.spec.mjs index ed33c2b52..91860ac1f 100644 --- a/ui/admin/tests/e2e/tests/credential-store-static-ent.spec.js +++ b/ui/admin/tests/e2e/tests/credential-store-static-ent.spec.mjs @@ -3,19 +3,20 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test, expect } = require('@playwright/test'); -const { execSync } = require('child_process'); +import { test, expect } from '@playwright/test'; -const { checkEnv, authenticatedState } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, checkBoundaryCli, - deleteOrgCli, -} = require('../helpers/boundary-cli'); -const CredentialStoresPage = require('../pages/credential-stores'); -const OrgsPage = require('../pages/orgs'); -const ProjectsPage = require('../pages/projects'); -const TargetsPage = require('../pages/targets'); + deleteScopeCli, + getOrgIdFromNameCli, +} from '../helpers/boundary-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'; test.use({ storageState: authenticatedState }); @@ -110,10 +111,9 @@ test('Multiple Credential Stores (ENT) @ent @aws @docker', async ({ page }) => { process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - if (org) { - await deleteOrgCli(org.id); + const orgId = await getOrgIdFromNameCli(orgName); + if (orgId) { + await deleteScopeCli(orgId); } } } diff --git a/ui/admin/tests/e2e/tests/credential-store-static.spec.js b/ui/admin/tests/e2e/tests/credential-store-static.spec.mjs similarity index 79% rename from ui/admin/tests/e2e/tests/credential-store-static.spec.js rename to ui/admin/tests/e2e/tests/credential-store-static.spec.mjs index 168f8ef86..5928d9e2b 100644 --- a/ui/admin/tests/e2e/tests/credential-store-static.spec.js +++ b/ui/admin/tests/e2e/tests/credential-store-static.spec.mjs @@ -3,22 +3,25 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test, expect } = require('@playwright/test'); -const { execSync } = require('child_process'); -const { readFile } = require('fs/promises'); -const { nanoid } = require('nanoid'); +import { test, expect } from '@playwright/test'; +import { readFile } from 'fs/promises'; +import { nanoid } from 'nanoid'; -const { checkEnv, authenticatedState } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, + authorizeSessionByTargetIdCli, checkBoundaryCli, - deleteOrgCli, - getSessionCli, -} = require('../helpers/boundary-cli'); -const CredentialStoresPage = require('../pages/credential-stores'); -const OrgsPage = require('../pages/orgs'); -const ProjectsPage = require('../pages/projects'); -const TargetsPage = require('../pages/targets'); + deleteScopeCli, + getOrgIdFromNameCli, + getProjectIdFromNameCli, + getTargetIdFromNameCli, +} from '../helpers/boundary-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'; test.use({ storageState: authenticatedState }); @@ -75,7 +78,10 @@ test('Static Credential Store (User & Key Pair) @ce @aws @docker', async ({ process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const session = await getSessionCli(orgName, projectName, targetName); + const orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); + const session = await authorizeSessionByTargetIdCli(targetId); const retrievedUser = session.item.credentials[0].credential.username; const retrievedKey = session.item.credentials[0].credential.private_key; @@ -95,10 +101,9 @@ test('Static Credential Store (User & Key Pair) @ce @aws @docker', async ({ process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - if (org) { - await deleteOrgCli(org.id); + const orgId = await getOrgIdFromNameCli(orgName); + if (orgId) { + await deleteScopeCli(orgId); } } } @@ -127,7 +132,10 @@ test('Static Credential Store (Username & Password) @ce @aws @docker', async ({ process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const session = await getSessionCli(orgName, projectName, targetName); + const orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); + const session = await authorizeSessionByTargetIdCli(targetId); const retrievedUser = session.item.credentials[0].credential.username; const retrievedPassword = session.item.credentials[0].credential.password; @@ -141,10 +149,9 @@ test('Static Credential Store (Username & Password) @ce @aws @docker', async ({ process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - if (org) { - await deleteOrgCli(org.id); + const orgId = await getOrgIdFromNameCli(orgName); + if (orgId) { + await deleteScopeCli(orgId); } } } @@ -190,7 +197,10 @@ test('Static Credential Store (JSON) @ce @aws @docker', async ({ page }) => { process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const session = await getSessionCli(orgName, projectName, targetName); + const orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); + const session = await authorizeSessionByTargetIdCli(targetId); const retrievedUser = session.item.credentials[0].credential.username; const retrievedPassword = session.item.credentials[0].credential.password; const retrievedId = session.item.credentials[0].credential.id; @@ -206,10 +216,9 @@ test('Static Credential Store (JSON) @ce @aws @docker', async ({ page }) => { process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - if (org) { - await deleteOrgCli(org.id); + const orgId = await getOrgIdFromNameCli(orgName); + if (orgId) { + await deleteScopeCli(orgId); } } } @@ -260,10 +269,9 @@ test('Multiple Credential Stores (CE) @ce @aws @docker', async ({ page }) => { process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - if (org) { - await deleteOrgCli(org.id); + const orgId = await getOrgIdFromNameCli(orgName); + if (orgId) { + await deleteScopeCli(orgId); } } } diff --git a/ui/admin/tests/e2e/tests/credential-store-vault.spec.js b/ui/admin/tests/e2e/tests/credential-store-vault.spec.mjs similarity index 69% rename from ui/admin/tests/e2e/tests/credential-store-vault.spec.js rename to ui/admin/tests/e2e/tests/credential-store-vault.spec.mjs index 93d109388..5ceda94e1 100644 --- a/ui/admin/tests/e2e/tests/credential-store-vault.spec.js +++ b/ui/admin/tests/e2e/tests/credential-store-vault.spec.mjs @@ -3,22 +3,27 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test, expect } = require('@playwright/test'); -const { execSync } = require('child_process'); -const { nanoid } = require('nanoid'); -const { readFile } = require('fs/promises'); +import { test, expect } from '@playwright/test'; +import { execSync } from 'child_process'; +import { nanoid } from 'nanoid'; +import { readFile } from 'fs/promises'; -const { checkEnv, authenticatedState } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, + authorizeSessionByTargetIdCli, checkBoundaryCli, - deleteOrgCli, -} = require('../helpers/boundary-cli'); -const { checkVaultCli } = require('../helpers/vault-cli'); -const CredentialStoresPage = require('../pages/credential-stores'); -const OrgsPage = require('../pages/orgs'); -const ProjectsPage = require('../pages/projects'); -const TargetsPage = require('../pages/targets'); + 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'; @@ -52,7 +57,7 @@ test.beforeEach(async ({ page }) => { test('Vault Credential Store (User & Key Pair) @ce @aws @docker', async ({ page, }) => { - let org; + let orgId; try { execSync( `vault policy write ${boundaryPolicyName} ./tests/e2e/tests/fixtures/boundary-controller-policy.hcl`, @@ -60,8 +65,8 @@ test('Vault Credential Store (User & Key Pair) @ce @aws @docker', async ({ execSync(`vault secrets enable -path=${secretsPath} kv-v2`); execSync( `vault kv put -mount ${secretsPath} ${secretName} ` + - ` username=${process.env.E2E_SSH_USER}` + - ` private_key=@${process.env.E2E_SSH_KEY_PATH}`, + ` username=${process.env.E2E_SSH_USER}` + + ` private_key=@${process.env.E2E_SSH_KEY_PATH}`, ); execSync( `vault policy write ${secretPolicyName} ./tests/e2e/tests/fixtures/kv-policy.hcl`, @@ -69,45 +74,26 @@ test('Vault Credential Store (User & Key Pair) @ce @aws @docker', async ({ const vaultToken = JSON.parse( execSync( `vault token create` + - ` -no-default-policy=true` + - ` -policy=${boundaryPolicyName}` + - ` -policy=${secretPolicyName}` + - ` -orphan=true` + - ` -period=20m` + - ` -renewable=true` + - ` -format=json`, + ` -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(); - await authenticateBoundaryCli( - process.env.BOUNDARY_ADDR, - process.env.E2E_PASSWORD_AUTH_METHOD_ID, - process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, - process.env.E2E_PASSWORD_ADMIN_PASSWORD, - ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - org = orgs.items.filter((obj) => obj.name == orgName)[0]; - const projectsPage = new ProjectsPage(page); const projectName = await projectsPage.createProject(); - 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 targetsPage = new TargetsPage(page); const targetName = await targetsPage.createTargetWithAddress( process.env.E2E_TARGET_ADDRESS, process.env.E2E_TARGET_PORT, ); - 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 credentialStoresPage = new CredentialStoresPage(page); await credentialStoresPage.createVaultCredentialStore( process.env.E2E_VAULT_ADDR, @@ -137,11 +123,16 @@ test('Vault Credential Store (User & Key Pair) @ce @aws @docker', async ({ credentialLibraryName, ); - const session = JSON.parse( - execSync( - `boundary targets authorize-session -id ${target.id} -format json`, - ), + await authenticateBoundaryCli( + process.env.BOUNDARY_ADDR, + process.env.E2E_PASSWORD_AUTH_METHOD_ID, + process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, + process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); + orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); + const session = await authorizeSessionByTargetIdCli(targetId); const retrievedUser = session.item.credentials[0].secret.decoded.data.username; const retrievedKey = @@ -156,8 +147,8 @@ test('Vault Credential Store (User & Key Pair) @ce @aws @docker', async ({ throw new Error('Stored Key does not match'); } } finally { - if (org) { - await deleteOrgCli(org.id); + if (orgId) { + await deleteScopeCli(orgId); } } }); diff --git a/ui/admin/tests/e2e/tests/delete-resources-ent.spec.js b/ui/admin/tests/e2e/tests/delete-resources-ent.spec.mjs similarity index 90% rename from ui/admin/tests/e2e/tests/delete-resources-ent.spec.js rename to ui/admin/tests/e2e/tests/delete-resources-ent.spec.mjs index 7ad4ed8e8..1eb79c8b6 100644 --- a/ui/admin/tests/e2e/tests/delete-resources-ent.spec.js +++ b/ui/admin/tests/e2e/tests/delete-resources-ent.spec.mjs @@ -3,11 +3,12 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test } = require('@playwright/test'); -const { execSync } = require('child_process'); +import { test } from '@playwright/test'; +import { execSync } from 'node:child_process'; -const { authenticatedState, checkEnv } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, checkBoundaryCli, createOrgCli, @@ -28,12 +29,12 @@ const { createSshTargetCli, createVaultCredentialStoreCli, createUsernamePasswordCredentialCli, - deleteOrgCli, -} = require('../helpers/boundary-cli'); -const { checkVaultCli } = require('../helpers/vault-cli'); -const AuthMethodsPage = require('../pages/auth-methods'); -const BaseResourcePage = require('../pages/base-resource'); -const WorkersPage = require('../pages/workers'); + deleteScopeCli, +} from '../helpers/boundary-cli.mjs'; +import { checkVaultCli, getVaultToken } from '../helpers/vault-cli.mjs'; +import { AuthMethodsPage } from '../pages/auth-methods.mjs'; +import { BaseResourcePage } from '../pages/base-resource.mjs'; +import { WorkersPage } from '../pages/workers.mjs'; const secretPolicyName = 'kv-policy'; const boundaryPolicyName = 'boundary-controller'; @@ -95,11 +96,14 @@ test('Verify resources can be deleted (enterprise) @ent @aws', async ({ let staticHostSetId = await createHostSetCli(staticHostCatalogId); let staticCredentialStoreId = await createStaticCredentialStoreCli(projectId); + const vaultToken = await getVaultToken( + boundaryPolicyName, + secretPolicyName, + ); let vaultCredentialStoreId = await createVaultCredentialStoreCli( projectId, process.env.E2E_VAULT_ADDR, - secretPolicyName, - boundaryPolicyName, + vaultToken, ); let usernamePasswordCredentialId = await createUsernamePasswordCredentialCli(staticCredentialStoreId); @@ -175,7 +179,7 @@ test('Verify resources can be deleted (enterprise) @ent @aws', async ({ orgDeleted = true; } finally { if (orgId && orgDeleted == false) { - await deleteOrgCli(orgId); + await deleteScopeCli(orgId); } } }); diff --git a/ui/admin/tests/e2e/tests/delete-resources.spec.js b/ui/admin/tests/e2e/tests/delete-resources.spec.mjs similarity index 91% rename from ui/admin/tests/e2e/tests/delete-resources.spec.js rename to ui/admin/tests/e2e/tests/delete-resources.spec.mjs index b55276c41..19109239c 100644 --- a/ui/admin/tests/e2e/tests/delete-resources.spec.js +++ b/ui/admin/tests/e2e/tests/delete-resources.spec.mjs @@ -3,11 +3,12 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test } = require('@playwright/test'); -const { execSync } = require('child_process'); +import { test } from '@playwright/test'; +import { execSync } from 'node:child_process'; -const { authenticatedState, checkEnv } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, checkBoundaryCli, createOrgCli, @@ -27,12 +28,12 @@ const { createTcpTarget, createVaultCredentialStoreCli, createUsernamePasswordCredentialCli, - deleteOrgCli, -} = require('../helpers/boundary-cli'); -const { checkVaultCli } = require('../helpers/vault-cli'); -const AuthMethodsPage = require('../pages/auth-methods'); -const BaseResourcePage = require('../pages/base-resource'); -const WorkersPage = require('../pages/workers'); + deleteScopeCli, +} from '../helpers/boundary-cli.mjs'; +import { checkVaultCli, getVaultToken } from '../helpers/vault-cli.mjs'; +import { AuthMethodsPage } from '../pages/auth-methods.mjs'; +import { BaseResourcePage } from '../pages/base-resource.mjs'; +import { WorkersPage } from '../pages/workers.mjs'; const secretPolicyName = 'kv-policy'; const boundaryPolicyName = 'boundary-controller'; @@ -91,11 +92,14 @@ test('Verify resources can be deleted @ce @aws', async ({ page }) => { let staticHostSetId = await createHostSetCli(staticHostCatalogId); let staticCredentialStoreId = await createStaticCredentialStoreCli(projectId); + const vaultToken = await getVaultToken( + boundaryPolicyName, + secretPolicyName, + ); let vaultCredentialStoreId = await createVaultCredentialStoreCli( projectId, process.env.E2E_VAULT_ADDR, - secretPolicyName, - boundaryPolicyName, + vaultToken, ); let usernamePasswordCredentialId = await createUsernamePasswordCredentialCli(staticCredentialStoreId); @@ -197,7 +201,7 @@ test('Verify resources can be deleted @ce @aws', async ({ page }) => { } finally { // Delete org in case the test failed before deleting the org using UI if (orgId && orgDeleted === false) { - await deleteOrgCli(orgId); + await deleteScopeCli(orgId); } } }); diff --git a/ui/admin/tests/e2e/tests/dynamic-host-catalog-aws.spec.js b/ui/admin/tests/e2e/tests/dynamic-host-catalog-aws.spec.mjs similarity index 90% rename from ui/admin/tests/e2e/tests/dynamic-host-catalog-aws.spec.js rename to ui/admin/tests/e2e/tests/dynamic-host-catalog-aws.spec.mjs index 47a192ba7..12d6d6c8b 100644 --- a/ui/admin/tests/e2e/tests/dynamic-host-catalog-aws.spec.js +++ b/ui/admin/tests/e2e/tests/dynamic-host-catalog-aws.spec.mjs @@ -3,19 +3,20 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test, expect } = require('@playwright/test'); -const { nanoid } = require('nanoid'); -import { execSync } from 'child_process'; +import { test, expect } from '@playwright/test'; +import { nanoid } from 'nanoid'; -const { checkEnv, authenticatedState } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, - deleteOrgCli, -} = require('../helpers/boundary-cli'); -const HostCatalogsPage = require('../pages/host-catalogs'); -const OrgsPage = require('../pages/orgs'); -const ProjectsPage = require('../pages/projects'); -const TargetsPage = require('../pages/targets'); + deleteScopeCli, + getOrgIdFromNameCli, +} from '../helpers/boundary-cli.mjs'; +import { HostCatalogsPage } from '../pages/host-catalogs.mjs'; +import { OrgsPage } from '../pages/orgs.mjs'; +import { ProjectsPage } from '../pages/projects.mjs'; +import { TargetsPage } from '../pages/targets.mjs'; test.use({ storageState: authenticatedState }); @@ -205,10 +206,9 @@ test.describe('AWS', async () => { ); if (orgName) { - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - if (org) { - await deleteOrgCli(org.id); + const orgId = await getOrgIdFromNameCli(orgName); + if (orgId) { + await deleteScopeCli(orgId); } } } diff --git a/ui/admin/tests/e2e/tests/global-settings.spec.js b/ui/admin/tests/e2e/tests/global-settings.spec.js deleted file mode 100644 index ba45ea55e..000000000 --- a/ui/admin/tests/e2e/tests/global-settings.spec.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -const { test, expect } = require('@playwright/test'); - -const { authenticatedState } = require('../helpers/general'); -const OrgsPage = require('../pages/orgs'); -const StoragePoliciesPage = require('../pages/storage-policies'); - -test.use({ storageState: authenticatedState }); - -test('Global Settings @ent @aws @docker', async ({ page }) => { - await page.goto('/'); - - // Create a storage policy - const storagePoliciesPage = new StoragePoliciesPage(page); - const policyName = await storagePoliciesPage.createStoragePolicy(); - const orgsPage = new OrgsPage(page); - await orgsPage.attachStoragePolicy(policyName); - - // Detach storage policy - await page.getByRole('button', { name: 'Manage', exact: true }).click(); - await page - .getByRole('button', { name: 'Detach Storage Policy', exact: true }) - .click(); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - await expect( - page.getByRole('alert').getByText('Success', { exact: true }), - ).toBeVisible(); - await page.getByRole('button', { name: 'Dismiss' }).click(); - - // Navigate to orgs page when done - await page - .getByRole('navigation', { name: 'General' }) - .getByRole('link', { name: 'Orgs' }) - .click(); - await expect(page.getByRole('heading', { name: 'Orgs' })).toBeVisible(); -}); diff --git a/ui/admin/tests/e2e/tests/global-settings.spec.mjs b/ui/admin/tests/e2e/tests/global-settings.spec.mjs new file mode 100644 index 000000000..7384949c2 --- /dev/null +++ b/ui/admin/tests/e2e/tests/global-settings.spec.mjs @@ -0,0 +1,61 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { test, expect } from '@playwright/test'; + +import { authenticatedState } from '../global-setup.mjs'; +import { + authenticateBoundaryCli, + deletePolicyCli, + getPolicyIdFromNameCli, +} from '../helpers/boundary-cli.mjs'; +import { OrgsPage } from '../pages/orgs.mjs'; +import { StoragePoliciesPage } from '../pages/storage-policies.mjs'; + +test.use({ storageState: authenticatedState }); + +test('Global Settings @ent @aws @docker', async ({ page }) => { + await page.goto('/'); + let policyName; + try { + // Create a storage policy + const storagePoliciesPage = new StoragePoliciesPage(page); + policyName = await storagePoliciesPage.createStoragePolicy(); + const orgsPage = new OrgsPage(page); + await orgsPage.attachStoragePolicy(policyName); + + // Detach storage policy + await page.getByRole('button', { name: 'Manage', exact: true }).click(); + await page + .getByRole('button', { name: 'Detach Storage Policy', exact: true }) + .click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await expect( + page.getByRole('alert').getByText('Success', { exact: true }), + ).toBeVisible(); + await page.getByRole('button', { name: 'Dismiss' }).click(); + + // Navigate to orgs page when done + await page + .getByRole('navigation', { name: 'General' }) + .getByRole('link', { name: 'Orgs' }) + .click(); + await expect(page.getByRole('heading', { name: 'Orgs' })).toBeVisible(); + } finally { + if (policyName) { + await authenticateBoundaryCli( + process.env.BOUNDARY_ADDR, + process.env.E2E_PASSWORD_AUTH_METHOD_ID, + process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, + process.env.E2E_PASSWORD_ADMIN_PASSWORD, + ); + const storagePolicyId = await getPolicyIdFromNameCli( + 'global', + policyName, + ); + await deletePolicyCli(storagePolicyId); + } + } +}); diff --git a/ui/admin/tests/e2e/tests/group-role.spec.js b/ui/admin/tests/e2e/tests/group-role.spec.mjs similarity index 66% rename from ui/admin/tests/e2e/tests/group-role.spec.js rename to ui/admin/tests/e2e/tests/group-role.spec.mjs index 699ce8a77..a4c489e7c 100644 --- a/ui/admin/tests/e2e/tests/group-role.spec.js +++ b/ui/admin/tests/e2e/tests/group-role.spec.mjs @@ -3,18 +3,18 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test } = require('@playwright/test'); -const { execSync } = require('child_process'); +import { test } from '@playwright/test'; -const { authenticatedState } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { authenticateBoundaryCli, checkBoundaryCli, - deleteOrgCli, -} = require('../helpers/boundary-cli'); -const GroupsPage = require('../pages/groups'); -const OrgsPage = require('../pages/orgs'); -const RolesPage = require('../pages/roles'); + deleteScopeCli, + getOrgIdFromNameCli, +} from '../helpers/boundary-cli.mjs'; +import { GroupsPage } from '../pages/groups.mjs'; +import { OrgsPage } from '../pages/orgs.mjs'; +import { RolesPage } from '../pages/roles.mjs'; test.use({ storageState: authenticatedState }); @@ -44,10 +44,9 @@ test('Verify a new role can be created and associated with a group @ce @ent @aws process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - if (org) { - await deleteOrgCli(org.id); + const orgId = await getOrgIdFromNameCli(orgName); + if (orgId) { + await deleteScopeCli(orgId); } } }); diff --git a/ui/admin/tests/e2e/tests/login.spec.js b/ui/admin/tests/e2e/tests/login.spec.mjs similarity index 98% rename from ui/admin/tests/e2e/tests/login.spec.js rename to ui/admin/tests/e2e/tests/login.spec.mjs index c270ff96b..05b3e76c8 100644 --- a/ui/admin/tests/e2e/tests/login.spec.js +++ b/ui/admin/tests/e2e/tests/login.spec.mjs @@ -3,7 +3,7 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test, expect } = require('@playwright/test'); +import { test, expect } from '@playwright/test'; test('Log in, log out, and then log back in @ce @ent @aws @docker', async ({ page, diff --git a/ui/admin/tests/e2e/tests/pagination.spec.js b/ui/admin/tests/e2e/tests/pagination.spec.mjs similarity index 98% rename from ui/admin/tests/e2e/tests/pagination.spec.js rename to ui/admin/tests/e2e/tests/pagination.spec.mjs index dcfb01508..364d6eb8d 100644 --- a/ui/admin/tests/e2e/tests/pagination.spec.js +++ b/ui/admin/tests/e2e/tests/pagination.spec.mjs @@ -3,10 +3,10 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test, expect } = require('@playwright/test'); +import { test, expect } from '@playwright/test'; import { nanoid } from 'nanoid'; -import { authenticatedState } from '../helpers/general'; +import { authenticatedState } from '../global-setup.mjs'; test.use({ storageState: authenticatedState }); diff --git a/ui/admin/tests/e2e/tests/session-recording-aws-ent.spec.js b/ui/admin/tests/e2e/tests/session-recording-aws-ent.spec.mjs similarity index 84% rename from ui/admin/tests/e2e/tests/session-recording-aws-ent.spec.js rename to ui/admin/tests/e2e/tests/session-recording-aws-ent.spec.mjs index 9823336d7..7ee893e7d 100644 --- a/ui/admin/tests/e2e/tests/session-recording-aws-ent.spec.js +++ b/ui/admin/tests/e2e/tests/session-recording-aws-ent.spec.mjs @@ -3,26 +3,31 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test, expect } = require('@playwright/test'); -const { execSync } = require('child_process'); +import { test, expect } from '@playwright/test'; +import { execSync } from 'child_process'; -const { checkEnv, authenticatedState } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, checkBoundaryCli, connectSshToTarget, - deleteOrgCli, + deleteScopeCli, waitForSessionRecordingCli, deleteStorageBucketCli, deletePolicyCli, -} = require('../helpers/boundary-cli'); -const CredentialStoresPage = require('../pages/credential-stores'); -const OrgsPage = require('../pages/orgs'); -const ProjectsPage = require('../pages/projects'); -const SessionsPage = require('../pages/sessions'); -const StorageBucketsPage = require('../pages/storage-buckets'); -const StoragePoliciesPage = require('../pages/storage-policies'); -const TargetsPage = require('../pages/targets'); + getOrgIdFromNameCli, + getPolicyIdFromNameCli, + getProjectIdFromNameCli, + getTargetIdFromNameCli, +} from '../helpers/boundary-cli.mjs'; +import { CredentialStoresPage } from '../pages/credential-stores.mjs'; +import { OrgsPage } from '../pages/orgs.mjs'; +import { ProjectsPage } from '../pages/projects.mjs'; +import { SessionsPage } from '../pages/sessions.mjs'; +import { StorageBucketsPage } from '../pages/storage-buckets.mjs'; +import { StoragePoliciesPage } from '../pages/storage-policies.mjs'; +import { TargetsPage } from '../pages/targets.mjs'; test.use({ storageState: authenticatedState }); @@ -45,31 +50,24 @@ test.beforeAll(async () => { test('Session Recording Test (AWS) @ent @aws', async ({ page }) => { await page.goto('/'); let orgId; - let storagePolicy; + let policyName; let storageBucket; let connect; try { - // Create org - const orgsPage = new OrgsPage(page); - const orgName = await orgsPage.createOrg(); await authenticateBoundaryCli( process.env.BOUNDARY_ADDR, process.env.E2E_PASSWORD_AUTH_METHOD_ID, process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - orgId = org.id; + + // Create org + const orgsPage = new OrgsPage(page); + const orgName = await orgsPage.createOrg(); // Create project const projectsPage = new ProjectsPage(page); const projectName = await projectsPage.createProject(); - 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 projectId = project.id; // Create storage bucket await page.getByRole('link', { name: 'Orgs', exact: true }).click(); @@ -102,10 +100,6 @@ test('Session Recording Test (AWS) @ent @aws', async ({ page }) => { await targetsPage.addEgressWorkerFilterToTarget( `"${process.env.E2E_WORKER_TAG_EGRESS}" in "/tags/type"`, ); - const targets = JSON.parse( - execSync('boundary targets list -format json -scope-id ' + projectId), - ); - const target = targets.items.filter((obj) => obj.name == targetName)[0]; const credentialStoresPage = new CredentialStoresPage(page); await credentialStoresPage.createStaticCredentialStore(); const credentialName = @@ -128,11 +122,14 @@ test('Session Recording Test (AWS) @ent @aws', async ({ page }) => { page.getByRole('navigation', { name: 'breadcrumbs' }).getByText(orgName), ).toBeVisible(); const storagePoliciesPage = new StoragePoliciesPage(page); - const policyName = await storagePoliciesPage.createStoragePolicy(); + policyName = await storagePoliciesPage.createStoragePolicy(); await orgsPage.attachStoragePolicy(policyName); // Establish connection to target and cancel it - connect = await connectSshToTarget(target.id); + orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); + connect = await connectSshToTarget(targetId); await page.getByRole('link', { name: 'Projects', exact: true }).click(); await page.getByRole('link', { name: projectName }).click(); const sessionsPage = new SessionsPage(page); @@ -185,12 +182,6 @@ test('Session Recording Test (AWS) @ent @aws', async ({ page }) => { await page.getByRole('button', { name: 'Dismiss' }).click(); // Edit storage policy: do not protect from deletion - const storagePolicies = JSON.parse( - execSync('boundary policies list -format json -scope-id ' + orgId), - ); - storagePolicy = storagePolicies.items.filter( - (obj) => obj.name == policyName, - )[0]; await page.getByRole('link', { name: 'Orgs', exact: true }).click(); await expect(page.getByRole('heading', { name: 'Orgs' })).toBeVisible(); await page.getByRole('link', { name: orgName }).click(); @@ -259,14 +250,15 @@ test('Session Recording Test (AWS) @ent @aws', async ({ page }) => { ).toBeVisible(); await page.getByRole('button', { name: 'Dismiss' }).click(); } finally { - if (storagePolicy) { - await deletePolicyCli(storagePolicy.id); + if (policyName) { + const storagePolicyId = await getPolicyIdFromNameCli(orgId, policyName); + await deletePolicyCli(storagePolicyId); } if (storageBucket) { await deleteStorageBucketCli(storageBucket.id); } if (orgId) { - await deleteOrgCli(orgId); + await deleteScopeCli(orgId); } // End `boundary connect` process if (connect) { diff --git a/ui/admin/tests/e2e/tests/session-recording-minio-ent.spec.js b/ui/admin/tests/e2e/tests/session-recording-minio-ent.spec.mjs similarity index 84% rename from ui/admin/tests/e2e/tests/session-recording-minio-ent.spec.js rename to ui/admin/tests/e2e/tests/session-recording-minio-ent.spec.mjs index 94ea99c2a..a9de6c557 100644 --- a/ui/admin/tests/e2e/tests/session-recording-minio-ent.spec.js +++ b/ui/admin/tests/e2e/tests/session-recording-minio-ent.spec.mjs @@ -3,26 +3,31 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test, expect } = require('@playwright/test'); -const { execSync } = require('child_process'); +import { test, expect } from '@playwright/test'; +import { execSync } from 'child_process'; -const { checkEnv, authenticatedState } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, checkBoundaryCli, connectSshToTarget, - deleteOrgCli, + deleteScopeCli, waitForSessionRecordingCli, deleteStorageBucketCli, deletePolicyCli, -} = require('../helpers/boundary-cli'); -const CredentialStoresPage = require('../pages/credential-stores'); -const OrgsPage = require('../pages/orgs'); -const ProjectsPage = require('../pages/projects'); -const SessionsPage = require('../pages/sessions'); -const StorageBucketsPage = require('../pages/storage-buckets'); -const StoragePoliciesPage = require('../pages/storage-policies'); -const TargetsPage = require('../pages/targets'); + getOrgIdFromNameCli, + getPolicyIdFromNameCli, + getProjectIdFromNameCli, + getTargetIdFromNameCli, +} from '../helpers/boundary-cli.mjs'; +import { CredentialStoresPage } from '../pages/credential-stores.mjs'; +import { OrgsPage } from '../pages/orgs.mjs'; +import { ProjectsPage } from '../pages/projects.mjs'; +import { SessionsPage } from '../pages/sessions.mjs'; +import { StorageBucketsPage } from '../pages/storage-buckets.mjs'; +import { StoragePoliciesPage } from '../pages/storage-policies.mjs'; +import { TargetsPage } from '../pages/targets.mjs'; test.use({ storageState: authenticatedState }); @@ -46,31 +51,24 @@ test('Session Recording Test (MinIO) @ent @docker', async ({ page }) => { await page.goto('/'); let orgId; - let storagePolicy; + let policyName; let storageBucket; let connect; try { - // Create org - const orgsPage = new OrgsPage(page); - const orgName = await orgsPage.createOrg(); await authenticateBoundaryCli( process.env.BOUNDARY_ADDR, process.env.E2E_PASSWORD_AUTH_METHOD_ID, process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name == orgName)[0]; - orgId = org.id; + + // Create org + const orgsPage = new OrgsPage(page); + const orgName = await orgsPage.createOrg(); // Create project const projectsPage = new ProjectsPage(page); const projectName = await projectsPage.createProject(); - 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 projectId = project.id; // Create storage bucket await page.getByRole('link', { name: 'Orgs', exact: true }).click(); @@ -105,10 +103,6 @@ test('Session Recording Test (MinIO) @ent @docker', async ({ page }) => { `"${process.env.E2E_WORKER_TAG_EGRESS}" in "/tags/type"`, ); - const targets = JSON.parse( - execSync('boundary targets list -format json -scope-id ' + projectId), - ); - const target = targets.items.filter((obj) => obj.name == targetName)[0]; const credentialStoresPage = new CredentialStoresPage(page); await credentialStoresPage.createStaticCredentialStore(); const credentialName = @@ -131,11 +125,14 @@ test('Session Recording Test (MinIO) @ent @docker', async ({ page }) => { page.getByRole('navigation', { name: 'breadcrumbs' }).getByText(orgName), ).toBeVisible(); const storagePoliciesPage = new StoragePoliciesPage(page); - const policyName = await storagePoliciesPage.createStoragePolicy(); + policyName = await storagePoliciesPage.createStoragePolicy(); await orgsPage.attachStoragePolicy(policyName); // Establish connection to target and cancel it - connect = await connectSshToTarget(target.id); + orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); + connect = await connectSshToTarget(targetId); await page.getByRole('link', { name: 'Projects', exact: true }).click(); await page.getByRole('link', { name: projectName }).click(); const sessionsPage = new SessionsPage(page); @@ -188,12 +185,6 @@ test('Session Recording Test (MinIO) @ent @docker', async ({ page }) => { await page.getByRole('button', { name: 'Dismiss' }).click(); // Edit storage policy: do not protect from deletion - const storagePolicies = JSON.parse( - execSync('boundary policies list -format json -scope-id ' + orgId), - ); - storagePolicy = storagePolicies.items.filter( - (obj) => obj.name == policyName, - )[0]; await page.getByRole('link', { name: 'Orgs', exact: true }).click(); await expect(page.getByRole('heading', { name: 'Orgs' })).toBeVisible(); await page.getByRole('link', { name: orgName }).click(); @@ -262,14 +253,15 @@ test('Session Recording Test (MinIO) @ent @docker', async ({ page }) => { ).toBeVisible(); await page.getByRole('button', { name: 'Dismiss' }).click(); } finally { - if (storagePolicy) { - await deletePolicyCli(storagePolicy.id); + if (policyName) { + const storagePolicyId = await getPolicyIdFromNameCli(orgId, policyName); + await deletePolicyCli(storagePolicyId); } if (storageBucket) { await deleteStorageBucketCli(storageBucket.id); } if (orgId) { - await deleteOrgCli(orgId); + await deleteScopeCli(orgId); } // End `boundary connect` process if (connect) { diff --git a/ui/admin/tests/e2e/tests/ssh-certificate-injection-vault-ent.spec.js b/ui/admin/tests/e2e/tests/ssh-certificate-injection-vault-ent.spec.mjs similarity index 70% rename from ui/admin/tests/e2e/tests/ssh-certificate-injection-vault-ent.spec.js rename to ui/admin/tests/e2e/tests/ssh-certificate-injection-vault-ent.spec.mjs index f80349e96..64453a443 100644 --- a/ui/admin/tests/e2e/tests/ssh-certificate-injection-vault-ent.spec.js +++ b/ui/admin/tests/e2e/tests/ssh-certificate-injection-vault-ent.spec.mjs @@ -3,22 +3,26 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test } = require('@playwright/test'); -const { execSync } = require('child_process'); +import { test } from '@playwright/test'; +import { execSync } from 'child_process'; -const { checkEnv, authenticatedState } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, checkBoundaryCli, connectSshToTarget, - deleteOrgCli, -} = require('../helpers/boundary-cli'); -const { checkVaultCli } = require('../helpers/vault-cli'); -const CredentialStoresPage = require('../pages/credential-stores'); -const OrgsPage = require('../pages/orgs'); -const ProjectsPage = require('../pages/projects'); -const SessionsPage = require('../pages/sessions'); -const TargetsPage = require('../pages/targets'); + 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 { SessionsPage } from '../pages/sessions.mjs'; +import { TargetsPage } from '../pages/targets.mjs'; const sshPolicyName = 'ssh-policy'; const boundaryPolicyName = 'boundary-controller'; @@ -51,7 +55,7 @@ test.beforeEach(async () => { test('SSH Certificate Injection @ent @docker', async ({ page }) => { await page.goto('/'); - let org; + let orgId; let connect; try { // Set up vault @@ -71,22 +75,22 @@ test('SSH Certificate Injection @ent @docker', async ({ page }) => { execSync( `vault write ${secretsPath}/config/ca` + - ` private_key="${private_key}"` + - ` public_key="${public_key}"` + - ` generate_signing_key=false`, + ` private_key="${private_key}"` + + ` public_key="${public_key}"` + + ` generate_signing_key=false`, ` format=json`, ); const vaultToken = JSON.parse( execSync( `vault token create` + - ` -no-default-policy=true` + - ` -policy=${boundaryPolicyName}` + - ` -policy=${sshPolicyName}` + - ` -orphan=true` + - ` -period=20m` + - ` -renewable=true` + - ` -format=json`, + ` -no-default-policy=true` + + ` -policy=${boundaryPolicyName}` + + ` -policy=${sshPolicyName}` + + ` -orphan=true` + + ` -period=20m` + + ` -renewable=true` + + ` -format=json`, ), ); const clientToken = vaultToken.auth.client_token; @@ -94,22 +98,10 @@ test('SSH Certificate Injection @ent @docker', async ({ page }) => { // Create org const orgsPage = new OrgsPage(page); const orgName = await orgsPage.createOrg(); - await authenticateBoundaryCli( - process.env.BOUNDARY_ADDR, - process.env.E2E_PASSWORD_AUTH_METHOD_ID, - process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, - process.env.E2E_PASSWORD_ADMIN_PASSWORD, - ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - org = orgs.items.filter((obj) => obj.name == orgName)[0]; // Create project const projectsPage = new ProjectsPage(page); const projectName = await projectsPage.createProject(); - const projects = JSON.parse( - execSync('boundary scopes list -format json -scope-id ' + org.id), - ); - const project = projects.items.filter((obj) => obj.name == projectName)[0]; // Create target const targetsPage = new TargetsPage(page); @@ -117,10 +109,6 @@ test('SSH Certificate Injection @ent @docker', async ({ page }) => { process.env.E2E_TARGET_ADDRESS, process.env.E2E_TARGET_PORT, ); - const targets = JSON.parse( - execSync('boundary targets list -format json -scope-id ' + project.id), - ); - const target = targets.items.filter((obj) => obj.name == targetName)[0]; // Create credentials const credentialStoresPage = new CredentialStoresPage(page); @@ -139,7 +127,16 @@ test('SSH Certificate Injection @ent @docker', async ({ page }) => { ); // Connect to target - connect = await connectSshToTarget(target.id); + await authenticateBoundaryCli( + process.env.BOUNDARY_ADDR, + process.env.E2E_PASSWORD_AUTH_METHOD_ID, + process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, + process.env.E2E_PASSWORD_ADMIN_PASSWORD, + ); + orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); + connect = await connectSshToTarget(targetId); const sessionsPage = new SessionsPage(page); await sessionsPage.waitForSessionToBeVisible(targetName); await page @@ -148,8 +145,8 @@ test('SSH Certificate Injection @ent @docker', async ({ page }) => { .getByRole('button', { name: 'Cancel' }) .click(); } finally { - if (org) { - await deleteOrgCli(org.id); + if (orgId) { + await deleteScopeCli(orgId); } // End `boundary connect` process if (connect) { diff --git a/ui/admin/tests/e2e/tests/ssh-credential-injection-vault-ent.spec.js b/ui/admin/tests/e2e/tests/ssh-credential-injection-vault-ent.spec.mjs similarity index 67% rename from ui/admin/tests/e2e/tests/ssh-credential-injection-vault-ent.spec.js rename to ui/admin/tests/e2e/tests/ssh-credential-injection-vault-ent.spec.mjs index 2243dc6d5..604979db8 100644 --- a/ui/admin/tests/e2e/tests/ssh-credential-injection-vault-ent.spec.js +++ b/ui/admin/tests/e2e/tests/ssh-credential-injection-vault-ent.spec.mjs @@ -3,22 +3,26 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test } = require('@playwright/test'); -const { execSync } = require('child_process'); +import { test } from '@playwright/test'; +import { execSync } from 'child_process'; -const { checkEnv, authenticatedState } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, checkBoundaryCli, connectSshToTarget, - deleteOrgCli, -} = require('../helpers/boundary-cli'); -const { checkVaultCli } = require('../helpers/vault-cli'); -const CredentialStoresPage = require('../pages/credential-stores'); -const OrgsPage = require('../pages/orgs'); -const ProjectsPage = require('../pages/projects'); -const SessionsPage = require('../pages/sessions'); -const TargetsPage = require('../pages/targets'); + 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 { SessionsPage } from '../pages/sessions.mjs'; +import { TargetsPage } from '../pages/targets.mjs'; const secretsPath = 'e2e_secrets'; const secretName = 'cred'; @@ -52,7 +56,7 @@ test.beforeEach(async ({ page }) => { test('SSH Credential Injection (Vault User & Key Pair) @ent @docker', async ({ page, }) => { - let org; + let orgId; let connect; try { // Set up vault @@ -62,8 +66,8 @@ test('SSH Credential Injection (Vault User & Key Pair) @ent @docker', async ({ execSync(`vault secrets enable -path=${secretsPath} kv-v2`); execSync( `vault kv put -mount ${secretsPath} ${secretName} ` + - ` username=${process.env.E2E_SSH_USER}` + - ` private_key=@${process.env.E2E_SSH_KEY_PATH}`, + ` username=${process.env.E2E_SSH_USER}` + + ` private_key=@${process.env.E2E_SSH_KEY_PATH}`, ); execSync( `vault policy write ${secretPolicyName} ./tests/e2e/tests/fixtures/kv-policy.hcl`, @@ -71,13 +75,13 @@ test('SSH Credential Injection (Vault User & Key Pair) @ent @docker', async ({ const vaultToken = JSON.parse( execSync( `vault token create` + - ` -no-default-policy=true` + - ` -policy=${boundaryPolicyName}` + - ` -policy=${secretPolicyName}` + - ` -orphan=true` + - ` -period=20m` + - ` -renewable=true` + - ` -format=json`, + ` -no-default-policy=true` + + ` -policy=${boundaryPolicyName}` + + ` -policy=${secretPolicyName}` + + ` -orphan=true` + + ` -period=20m` + + ` -renewable=true` + + ` -format=json`, ), ); const clientToken = vaultToken.auth.client_token; @@ -85,22 +89,10 @@ test('SSH Credential Injection (Vault User & Key Pair) @ent @docker', async ({ // Create org const orgsPage = new OrgsPage(page); const orgName = await orgsPage.createOrg(); - await authenticateBoundaryCli( - process.env.BOUNDARY_ADDR, - process.env.E2E_PASSWORD_AUTH_METHOD_ID, - process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, - process.env.E2E_PASSWORD_ADMIN_PASSWORD, - ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - org = orgs.items.filter((obj) => obj.name == orgName)[0]; // Create project const projectsPage = new ProjectsPage(page); const projectName = await projectsPage.createProject(); - const projects = JSON.parse( - execSync('boundary scopes list -format json -scope-id ' + org.id), - ); - const project = projects.items.filter((obj) => obj.name == projectName)[0]; // Create target const targetsPage = new TargetsPage(page); @@ -108,10 +100,6 @@ test('SSH Credential Injection (Vault User & Key Pair) @ent @docker', async ({ process.env.E2E_TARGET_ADDRESS, process.env.E2E_TARGET_PORT, ); - const targets = JSON.parse( - execSync('boundary targets list -format json -scope-id ' + project.id), - ); - const target = targets.items.filter((obj) => obj.name == targetName)[0]; // Create credentials const credentialStoresPage = new CredentialStoresPage(page); @@ -130,7 +118,16 @@ test('SSH Credential Injection (Vault User & Key Pair) @ent @docker', async ({ ); // Connect to target - connect = await connectSshToTarget(target.id); + await authenticateBoundaryCli( + process.env.BOUNDARY_ADDR, + process.env.E2E_PASSWORD_AUTH_METHOD_ID, + process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, + process.env.E2E_PASSWORD_ADMIN_PASSWORD, + ); + orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); + connect = await connectSshToTarget(targetId); const sessionsPage = new SessionsPage(page); await sessionsPage.waitForSessionToBeVisible(targetName); await page @@ -139,8 +136,8 @@ test('SSH Credential Injection (Vault User & Key Pair) @ent @docker', async ({ .getByRole('button', { name: 'Cancel' }) .click(); } finally { - if (org) { - await deleteOrgCli(org.id); + if (orgId) { + await deleteScopeCli(orgId); } // End `boundary connect` process if (connect) { diff --git a/ui/admin/tests/e2e/tests/target-ent.spec.js b/ui/admin/tests/e2e/tests/target-ent.spec.mjs similarity index 71% rename from ui/admin/tests/e2e/tests/target-ent.spec.js rename to ui/admin/tests/e2e/tests/target-ent.spec.mjs index c1a840d0a..c8354c261 100644 --- a/ui/admin/tests/e2e/tests/target-ent.spec.js +++ b/ui/admin/tests/e2e/tests/target-ent.spec.mjs @@ -3,23 +3,26 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test, expect } = require('@playwright/test'); -const { execSync } = require('child_process'); +import { test, expect } from '@playwright/test'; -const { checkEnv, authenticatedState } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, checkBoundaryCli, connectToTarget, connectSshToTarget, - deleteOrgCli, -} = require('../helpers/boundary-cli'); -const CredentialStoresPage = require('../pages/credential-stores'); -const HostCatalogsPage = require('../pages/host-catalogs'); -const OrgsPage = require('../pages/orgs'); -const ProjectsPage = require('../pages/projects'); -const SessionsPage = require('../pages/sessions'); -const TargetsPage = require('../pages/targets'); + deleteScopeCli, + getOrgIdFromNameCli, + getProjectIdFromNameCli, + getTargetIdFromNameCli, +} from '../helpers/boundary-cli.mjs'; +import { CredentialStoresPage } from '../pages/credential-stores.mjs'; +import { HostCatalogsPage } from '../pages/host-catalogs.mjs'; +import { OrgsPage } from '../pages/orgs.mjs'; +import { ProjectsPage } from '../pages/projects.mjs'; +import { SessionsPage } from '../pages/sessions.mjs'; +import { TargetsPage } from '../pages/targets.mjs'; test.use({ storageState: authenticatedState }); @@ -38,39 +41,30 @@ test('Verify session created for TCP target @ent @aws @docker', async ({ page, }) => { await page.goto('/'); - let org; + let orgId; let connect; try { 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.createTcpTargetWithAddressEnt( + process.env.E2E_TARGET_ADDRESS, + process.env.E2E_TARGET_PORT, + ); + await authenticateBoundaryCli( process.env.BOUNDARY_ADDR, process.env.E2E_PASSWORD_AUTH_METHOD_ID, process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - org = orgs.items.filter((obj) => obj.name == orgName)[0]; - - const projectsPage = new ProjectsPage(page); - const projectName = await projectsPage.createProject(); - 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 targetsPage = new TargetsPage(page); - const targetName = await targetsPage.createTcpTargetWithAddressEnt( - process.env.E2E_TARGET_ADDRESS, - process.env.E2E_TARGET_PORT, - ); - const targets = JSON.parse( - execSync('boundary targets list -format json -scope-id ' + project.id), - ); - const target = targets.items.filter((obj) => obj.name == targetName)[0]; - + orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); connect = await connectToTarget( - target.id, + targetId, process.env.E2E_SSH_USER, process.env.E2E_SSH_KEY_PATH, ); @@ -82,8 +76,8 @@ test('Verify session created for TCP target @ent @aws @docker', async ({ .getByRole('button', { name: 'Cancel' }) .click(); } finally { - if (org) { - await deleteOrgCli(org.id); + if (orgId) { + await deleteScopeCli(orgId); } // End `boundary connect` process if (connect) { @@ -96,37 +90,18 @@ test('Verify session created for SSH target @ent @aws @docker', async ({ page, }) => { await page.goto('/'); - let org; + let orgId; let connect; try { const orgsPage = new OrgsPage(page); const orgName = await orgsPage.createOrg(); - await authenticateBoundaryCli( - process.env.BOUNDARY_ADDR, - process.env.E2E_PASSWORD_AUTH_METHOD_ID, - process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, - process.env.E2E_PASSWORD_ADMIN_PASSWORD, - ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - org = orgs.items.filter((obj) => obj.name == orgName)[0]; - const projectsPage = new ProjectsPage(page); const projectName = await projectsPage.createProject(); - 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 targetsPage = new TargetsPage(page); const targetName = await targetsPage.createSshTargetWithAddressEnt( process.env.E2E_TARGET_ADDRESS, process.env.E2E_TARGET_PORT, ); - 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 credentialStoresPage = new CredentialStoresPage(page); await credentialStoresPage.createStaticCredentialStore(); const credentialName = @@ -139,7 +114,16 @@ test('Verify session created for SSH target @ent @aws @docker', async ({ credentialName, ); - connect = await connectSshToTarget(target.id); + await authenticateBoundaryCli( + process.env.BOUNDARY_ADDR, + process.env.E2E_PASSWORD_AUTH_METHOD_ID, + process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, + process.env.E2E_PASSWORD_ADMIN_PASSWORD, + ); + orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); + connect = await connectSshToTarget(targetId); const sessionsPage = new SessionsPage(page); await sessionsPage.waitForSessionToBeVisible(targetName); await page @@ -148,8 +132,8 @@ test('Verify session created for SSH target @ent @aws @docker', async ({ .getByRole('button', { name: 'Cancel' }) .click(); } finally { - if (org) { - await deleteOrgCli(org.id); + if (orgId) { + await deleteScopeCli(orgId); } // End `boundary connect` process if (connect) { @@ -160,7 +144,7 @@ test('Verify session created for SSH target @ent @aws @docker', async ({ test('SSH target with host sources @ent @aws @docker', async ({ page }) => { await page.goto('/'); - let org; + let orgId; let connect; try { const orgsPage = new OrgsPage(page); @@ -224,17 +208,10 @@ test('SSH target with host sources @ent @aws @docker', async ({ page }) => { process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - 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]; - connect = await connectSshToTarget(target.id); + orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); + connect = await connectSshToTarget(targetId); const sessionsPage = new SessionsPage(page); await sessionsPage.waitForSessionToBeVisible(targetName); await page @@ -243,8 +220,8 @@ test('SSH target with host sources @ent @aws @docker', async ({ page }) => { .getByRole('button', { name: 'Cancel' }) .click(); } finally { - if (org) { - await deleteOrgCli(org.id); + if (orgId) { + await deleteScopeCli(orgId); } // End `boundary connect` process if (connect) { diff --git a/ui/admin/tests/e2e/tests/target.spec.js b/ui/admin/tests/e2e/tests/target.spec.mjs similarity index 75% rename from ui/admin/tests/e2e/tests/target.spec.js rename to ui/admin/tests/e2e/tests/target.spec.mjs index 1ee97575c..2c5b72812 100644 --- a/ui/admin/tests/e2e/tests/target.spec.js +++ b/ui/admin/tests/e2e/tests/target.spec.mjs @@ -3,21 +3,24 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { test, expect } = require('@playwright/test'); -const { execSync } = require('child_process'); +import { test, expect } from '@playwright/test'; -const { checkEnv, authenticatedState } = require('../helpers/general'); -const { +import { authenticatedState } from '../global-setup.mjs'; +import { checkEnv } from '../helpers/general.mjs'; +import { authenticateBoundaryCli, checkBoundaryCli, connectToTarget, - deleteOrgCli, -} = require('../helpers/boundary-cli'); -const HostCatalogsPage = require('../pages/host-catalogs'); -const OrgsPage = require('../pages/orgs'); -const ProjectsPage = require('../pages/projects'); -const SessionsPage = require('../pages/sessions'); -const TargetsPage = require('../pages/targets'); + deleteScopeCli, + getOrgIdFromNameCli, + getProjectIdFromNameCli, + getTargetIdFromNameCli, +} from '../helpers/boundary-cli.mjs'; +import { HostCatalogsPage } from '../pages/host-catalogs.mjs'; +import { OrgsPage } from '../pages/orgs.mjs'; +import { ProjectsPage } from '../pages/projects.mjs'; +import { SessionsPage } from '../pages/sessions.mjs'; +import { TargetsPage } from '../pages/targets.mjs'; test.use({ storageState: authenticatedState }); @@ -36,7 +39,7 @@ test('Verify session created to target with host, then cancel the session @ce @a page, }) => { await page.goto('/'); - let org; + let orgId; let connect; try { const orgsPage = new OrgsPage(page); @@ -87,19 +90,11 @@ test('Verify session created to target with host, then cancel the session @ce @a process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - 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]; - + orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); connect = await connectToTarget( - target.id, + targetId, process.env.E2E_SSH_USER, process.env.E2E_SSH_KEY_PATH, ); @@ -111,8 +106,8 @@ test('Verify session created to target with host, then cancel the session @ce @a .getByRole('button', { name: 'Cancel' }) .click(); } finally { - if (org) { - await deleteOrgCli(org.id); + if (orgId) { + await deleteScopeCli(orgId); } // End `boundary connect` process if (connect) { @@ -125,7 +120,7 @@ test('Verify session created to target with address, then cancel the session @ce page, }) => { await page.goto('/'); - let org; + let orgId; let connect; try { const orgsPage = new OrgsPage(page); @@ -144,19 +139,11 @@ test('Verify session created to target with address, then cancel the session @ce process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - 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]; - + orgId = await getOrgIdFromNameCli(orgName); + const projectId = await getProjectIdFromNameCli(orgId, projectName); + const targetId = await getTargetIdFromNameCli(projectId, targetName); connect = await connectToTarget( - target.id, + targetId, process.env.E2E_SSH_USER, process.env.E2E_SSH_KEY_PATH, ); @@ -168,8 +155,8 @@ test('Verify session created to target with address, then cancel the session @ce .getByRole('button', { name: 'Cancel' }) .click(); } finally { - if (org) { - await deleteOrgCli(org.id); + if (orgId) { + await deleteScopeCli(orgId); } // End `boundary connect` process if (connect) { @@ -216,10 +203,9 @@ test('Verify TCP target is updated @ce @aws @docker', async ({ page }) => { process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME, process.env.E2E_PASSWORD_ADMIN_PASSWORD, ); - const orgs = JSON.parse(execSync('boundary scopes list -format json')); - const org = orgs.items.filter((obj) => obj.name === orgName)[0]; - if (org) { - await deleteOrgCli(org.id); + const orgId = await getOrgIdFromNameCli(orgName); + if (orgId) { + await deleteScopeCli(orgId); } } }); diff --git a/ui/admin/tests/e2e/tests/worker-ent.spec.js b/ui/admin/tests/e2e/tests/worker-ent.spec.mjs similarity index 95% rename from ui/admin/tests/e2e/tests/worker-ent.spec.js rename to ui/admin/tests/e2e/tests/worker-ent.spec.mjs index 486e01185..4b3e372a5 100644 --- a/ui/admin/tests/e2e/tests/worker-ent.spec.js +++ b/ui/admin/tests/e2e/tests/worker-ent.spec.mjs @@ -3,10 +3,9 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); -const { test } = require('@playwright/test'); +import { test, expect } from '@playwright/test'; -const { authenticatedState } = require('../helpers/general'); +import { authenticatedState } from '../global-setup.mjs'; test.use({ storageState: authenticatedState }); diff --git a/ui/admin/tests/e2e/tests/worker.spec.js b/ui/admin/tests/e2e/tests/worker.spec.mjs similarity index 94% rename from ui/admin/tests/e2e/tests/worker.spec.js rename to ui/admin/tests/e2e/tests/worker.spec.mjs index ce5dcc53f..161640561 100644 --- a/ui/admin/tests/e2e/tests/worker.spec.js +++ b/ui/admin/tests/e2e/tests/worker.spec.mjs @@ -3,10 +3,9 @@ * SPDX-License-Identifier: BUSL-1.1 */ -const { expect } = require('@playwright/test'); -const { test } = require('@playwright/test'); +import { test, expect } from '@playwright/test'; -const { authenticatedState } = require('../helpers/general'); +import { authenticatedState } from '../global-setup.mjs'; test.use({ storageState: authenticatedState });